The Tofuri Project

Welcome to the Tofuri Project, a groundbreaking cryptocurrency initiative!

Tofuri is a unique cryptocurrency that employs the Proof-of-Stake (PoS) consensus algorithm. In contrast to traditional Proof-of-Work (PoW) cryptocurrencies, which demand high computational power and significant energy consumption, Tofuri aims to be more environmentally friendly and energy-efficient by leveraging PoS. This approach means that, instead of miners vying to solve intricate mathematical problems, validators are chosen at random to confirm transactions and safeguard the network.

This comprehensive guide delves deep into the Tofuri project and its underlying technology. We will explore topics such as the architecture and implementation of the Tofuri blockchain, the consensus algorithm utilized, the roles of validators and stakers, and much more. Whether you are a cryptocurrency novice or an experienced blockchain enthusiast, this guide will equip you with a thorough understanding of Tofuri and its potential to transform the cryptocurrency landscape.

Should you have any inquiries or require assistance related to Tofuri, please don't hesitate to contact us through our friendly and supportive Discord server. We have an inclusive community of Tofuri aficionados who are always eager to help and share their expertise with others. So, feel free to drop in, say hello, request help, or simply engage in conversation with us. We are excited to meet you!

Let's get started!

Getting Started

Welcome to the Tofuri Installation guide! This guide will walk you through the process of installing all the necessary software and tools required to run Tofuri on your machine. We will cover the installation of Rust and its package manager, Cargo, along with other build dependencies necessary for the project. By following the steps provided in this guide, you will have all the prerequisites installed and be ready to use Tofuri.

The installation process consists of the following steps:

  1. Installing Rust
  2. Installing Git
  3. Installing Build Dependencies
  4. Cloning the Repository
  5. Compiling and Running Tofuri

Installing Rust

Tofuri is written in Rust, so the first thing you need to do is install Rust and its package manager, Cargo. To install Rust, follow these steps:

  1. Visit the Rust website at https://www.rust-lang.org/tools/install.
  2. Follow the installation instructions for your operating system.
  3. Open a new terminal window to make sure Rust is installed correctly.
  4. Type rustc --version to check the version of Rust installed. If everything is working correctly, you should see the version number printed in the terminal.

Installing Git

Git is a version control system that is used to manage the source code for Tofuri. Follow these steps to install Git on your machine:

Windows

Git for Windows

  1. Visit the Git website at https://git-scm.com/download/win.
  2. Click the "Download" button to download the installer.
  3. Run the installer and follow the prompts.
  4. Open Git Bash to test that Git is installed correctly.
  5. Type git --version to check the version of Git installed. If everything is working correctly, you should see the version number printed in the terminal.

macOS

Homebrew

  1. Install Homebrew by following the instructions on their website at https://brew.sh.
  2. Open Terminal.app.
  3. Type brew install git to install Git using Homebrew.
  4. Type git --version to check the version of Git installed. If everything is working correctly, you should see the version number printed in the terminal.

Linux

Debian-based distributions

  1. Open a terminal window.
  2. Type sudo apt-get update to update your package list.
  3. Type sudo apt-get install git to install Git.
  4. Type git --version to check the version of Git installed. If everything is working correctly, you should see the version number printed in the terminal.

Arch-based distributions

  1. Open a terminal window.
  2. Type sudo pacman -Syu to update your package list.
  3. Type sudo pacman -S git to install Git.
  4. Type git --version to check the version of Git installed. If everything is working correctly, you should see the version number printed in the terminal.

Build Dependencies

Before you can build and run Tofuri, you will need to install some extra dependencies in addition to Rust. These dependencies include LLVM, CMake and Protobuf.

Please refer to the instructions below for your specific Linux distribution.

One option for Windows users is to manually download and install LLVM, CMake, Protobuf, and OpenSSL from their respective websites. However, it is generally recommended to use WSL instead.

Debian-based Linux Distributions

If you are using a Debian-based Linux distribution, you can install the necessary dependencies for Tofuri with the following command:

sudo apt install cmake clang protobuf-compiler libssl-dev pkg-config git

Arch-based Linux Distributions

If you are using an Arch-based Linux distribution, you can install the necessary dependencies for Tofuri with the following command:

sudo pacman -S cmake clang protobuf git

Cloning the Repository

To download the Tofuri source code, you need to clone the repository. You can do this by running the following command in a terminal window:

git clone https://github.com/tofuri/tofuri

This will create a new directory called "tofuri" containing the Tofuri source code.

Compiling and Running Tofuri

To compile and run Tofuri, navigate to the "tofuri" directory and run the following command:

cargo run

This will download and install all the necessary dependencies, compile the code, and start the Tofuri application. You should see some output in the terminal, indicating that the program is running.

Congratulations! You have successfully installed Tofuri on your machine. You can now proceed to the next page to learn more about the project.

Wallet

The Tofuri wallet is a software application that allows users to securely store, send and receive Tofuri. It provides an easy-to-use interface that makes managing your Tofuri simple and intuitive.

When you first download and install the Tofuri wallet, you will be prompted to create a new wallet or restore an existing one. If you are creating a new wallet, you will be asked to set a secure password and provided with a unique seed phrase. It is important to keep this seed phrase safe and secure, as it is used to recover your wallet in case you lose access to it.

Once your wallet is set up, you can receive Tofuri by providing your wallet address to other users. To send Tofuri, you simply enter the recipient's wallet address and the amount of coins you wish to send. The wallet will automatically calculate the transaction fee and display the total cost of the transaction.

To run the Tofuri wallet, you need to navigate to the cloned Tofuri repository in your command-line interface and enter the command:

cargo run --bin tofuri-wallet

Fullnode

A Fullnode in the Tofuri network is a software application that fully validates transactions and blocks on the Tofuri blockchain. It is an essential component of the Tofuri network and helps to maintain the integrity and security of the blockchain.

Running a Fullnode requires a significant amount of computational power and storage space, as it is responsible for processing and validating all transactions on the network. Fullnodes play a crucial role in the Tofuri network, as they help to prevent attacks such as double-spending and ensure that all transactions are processed accurately and securely.

To run a Fullnode on the Tofuri network, you will need to download and install the Tofuri software on your machine. Once installed, the Fullnode will start downloading the entire Tofuri blockchain and validating all the transactions on the network.

Running a Fullnode on the Tofuri network comes with several benefits. For example, it allows you to have complete control over your transactions and ensures that your transactions are validated and processed by a trusted node on the network. Additionally, running a Fullnode also allows you to contribute to the security and stability of the Tofuri network, making it a more decentralized and resilient platform.

In conclusion, running a Fullnode on the Tofuri network is an essential component for anyone looking to contribute to the security and stability of the blockchain. While it requires a significant amount of computational power and storage space, it comes with several benefits and is a vital part of the Tofuri ecosystem.

To run the Tofuri Fullnode, you need to navigate to the cloned Tofuri repository in your command-line interface and enter the command:

cargo run --bin tofuri-fullnode

Staking

Staking is a fundamental process in the Tofuri network that involves holding Tofuri in a Tofuri wallet or Fullnode to help secure the blockchain and earn rewards. It is a crucial part of Tofuri's Proof-of-Stake (PoS) consensus algorithm that maintains the network's integrity.

To participate in staking, users need to deposit a minimum amount of Tofuri that corresponds to the exact number of current active stakers. The minimum amount required to stake may vary based on the current network conditions and can be adjusted over time.

By staking their Tofuri, users can validate transactions and add new blocks to the Tofuri blockchain, earning rewards in the form of newly minted Tofuri coins for each block validated. Staking incentivizes users to contribute to the network's security and stability while reducing the risk of centralization.

In conclusion, staking is a critical aspect of the Tofuri ecosystem that rewards users for contributing to the network's success. By depositing the minimum required amount of Tofuri and participating in staking, users can validate transactions and secure the blockchain while earning rewards.

Protocol

In this section, we will be discussing the protocol features of Tofuri core. Tofuri is a proof-of-stake cryptocurrency designed to be fast, secure, and scalable. The Tofuri core is responsible for implementing the protocol features of the cryptocurrency, and it is written entirely in Rust. Understanding the protocol features of Tofuri core is essential for developers and users who want to work with or use the cryptocurrency. We will cover key features such as proof-of-stake consensus, the consensus algorithm used, transaction validation, and more. By the end of this section, you will have a better understanding of how Tofuri works and what makes it unique.

Transactions

Transactions are the fundamental building blocks of blockchain technology. They represent the movement of assets or information from one party to another within a decentralized network. Transactions are designed to be as efficient as possible, both in terms of speed and storage space required.

An important aspect of transaction design is the way that inputs are recovered. In many blockchain systems, inputs are recovered using a technique called public key recovery. This involves using cryptographic signatures to verify that the input is valid and belongs to the correct user. By using public key recovery, transactions can be validated quickly and securely, without the need for intermediaries or centralized authorities.

Filename: tofuri/transaction/src/lib.rs

use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_address::address;
use tofuri_core::*;
use tofuri_key::Key;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
}
pub trait Transaction {
    fn get_output_address(&self) -> &AddressBytes;
    fn get_timestamp(&self) -> u32;
    fn get_amount_bytes(&self) -> AmountBytes;
    fn get_fee_bytes(&self) -> AmountBytes;
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 32];
}
impl Transaction for TransactionA {
    fn get_output_address(&self) -> &AddressBytes {
        &self.output_address
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_amount_bytes(&self) -> AmountBytes {
        tofuri_int::to_be_bytes(self.amount)
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        tofuri_int::to_be_bytes(self.fee)
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 32] {
        hash_input(self)
    }
}
impl Transaction for TransactionB {
    fn get_output_address(&self) -> &AddressBytes {
        &self.output_address
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_amount_bytes(&self) -> AmountBytes {
        self.amount
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        self.fee
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 32] {
        hash_input(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct TransactionA {
    pub input_address: AddressBytes,
    pub output_address: AddressBytes,
    pub amount: u128,
    pub fee: u128,
    pub timestamp: u32,
    pub hash: Hash,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
}
impl fmt::Debug for TransactionA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("TransactionA")
            .field("input_address", &address::encode(&self.input_address))
            .field("output_address", &address::encode(&self.output_address))
            .field("amount", &tofuri_int::to_string(self.amount))
            .field("fee", &tofuri_int::to_string(self.fee))
            .field("timestamp", &self.timestamp.to_string())
            .field("hash", &hex::encode(&self.hash))
            .field("signature", &hex::encode(&self.signature))
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct TransactionB {
    pub output_address: AddressBytes,
    pub amount: AmountBytes,
    pub fee: AmountBytes,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
}
impl fmt::Debug for TransactionB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("TransactionB")
            .field("output_address", &address::encode(&self.output_address))
            .field("amount", &hex::encode(&self.amount))
            .field("fee", &hex::encode(&self.fee))
            .field("timestamp", &self.timestamp.to_string())
            .field("signature", &hex::encode(&self.signature))
            .finish()
    }
}
impl TransactionA {
    pub fn b(&self) -> TransactionB {
        TransactionB {
            output_address: self.output_address,
            amount: tofuri_int::to_be_bytes(self.amount),
            fee: tofuri_int::to_be_bytes(self.fee),
            timestamp: self.timestamp,
            signature: self.signature,
        }
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    pub fn sign(
        output_address: AddressBytes,
        amount: u128,
        fee: u128,
        timestamp: u32,
        key: &Key,
    ) -> Result<TransactionA, Error> {
        let mut transaction_a = TransactionA {
            input_address: [0; 20],
            output_address,
            amount: tofuri_int::floor(amount),
            fee: tofuri_int::floor(fee),
            timestamp,
            hash: [0; 32],
            signature: [0; 64],
        };
        transaction_a.hash = transaction_a.hash();
        transaction_a.signature = key.sign(&transaction_a.hash).map_err(Error::Key)?;
        transaction_a.input_address = key.address_bytes();
        Ok(transaction_a)
    }
}
impl TransactionB {
    pub fn a(&self, input_address: Option<AddressBytes>) -> Result<TransactionA, Error> {
        let input_address = input_address.unwrap_or(self.input_address()?);
        let transaction_a = TransactionA {
            output_address: self.output_address,
            amount: tofuri_int::from_be_slice(&self.amount),
            fee: tofuri_int::from_be_slice(&self.fee),
            timestamp: self.timestamp,
            signature: self.signature,
            input_address,
            hash: self.hash(),
        };
        Ok(transaction_a)
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    fn input_address(&self) -> Result<AddressBytes, Error> {
        Ok(Key::address(&self.input_public_key()?))
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
fn hash<T: Transaction>(transaction: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(transaction.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Transaction>(transaction: &T) -> [u8; 32] {
    let mut bytes = [0; 32];
    bytes[0..20].copy_from_slice(transaction.get_output_address());
    bytes[20..24].copy_from_slice(&transaction.get_timestamp().to_be_bytes());
    bytes[24..28].copy_from_slice(&transaction.get_amount_bytes());
    bytes[28..32].copy_from_slice(&transaction.get_fee_bytes());
    bytes
}
impl Default for TransactionA {
    fn default() -> TransactionA {
        TransactionA {
            output_address: [0; 20],
            amount: 0,
            fee: 0,
            timestamp: 0,
            signature: [0; 64],
            input_address: [0; 20],
            hash: [0; 32],
        }
    }
}
impl Default for TransactionB {
    fn default() -> TransactionB {
        TransactionB {
            output_address: [0; 20],
            amount: [0; AMOUNT_BYTES],
            fee: [0; AMOUNT_BYTES],
            timestamp: 0,
            signature: [0; 64],
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            TransactionB::default().hash(),
            [
                102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, 8,
                151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, 37
            ]
        );
    }
}
use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_address::address;
use tofuri_core::*;
use tofuri_key::Key;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
}
pub trait Transaction {
    fn get_output_address(&self) -> &AddressBytes;
    fn get_timestamp(&self) -> u32;
    fn get_amount_bytes(&self) -> AmountBytes;
    fn get_fee_bytes(&self) -> AmountBytes;
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 32];
}
impl Transaction for TransactionA {
    fn get_output_address(&self) -> &AddressBytes {
        &self.output_address
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_amount_bytes(&self) -> AmountBytes {
        tofuri_int::to_be_bytes(self.amount)
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        tofuri_int::to_be_bytes(self.fee)
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 32] {
        hash_input(self)
    }
}
impl Transaction for TransactionB {
    fn get_output_address(&self) -> &AddressBytes {
        &self.output_address
    }
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_amount_bytes(&self) -> AmountBytes {
        self.amount
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        self.fee
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 32] {
        hash_input(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct TransactionA {
    pub input_address: AddressBytes,
    pub output_address: AddressBytes,
    pub amount: u128,
    pub fee: u128,
    pub timestamp: u32,
    pub hash: Hash,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
}
impl fmt::Debug for TransactionA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("TransactionA")
            .field("input_address", &address::encode(&self.input_address))
            .field("output_address", &address::encode(&self.output_address))
            .field("amount", &tofuri_int::to_string(self.amount))
            .field("fee", &tofuri_int::to_string(self.fee))
            .field("timestamp", &self.timestamp.to_string())
            .field("hash", &hex::encode(&self.hash))
            .field("signature", &hex::encode(&self.signature))
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct TransactionB {
    pub output_address: AddressBytes,
    pub amount: AmountBytes,
    pub fee: AmountBytes,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
}
impl fmt::Debug for TransactionB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("TransactionB")
            .field("output_address", &address::encode(&self.output_address))
            .field("amount", &hex::encode(&self.amount))
            .field("fee", &hex::encode(&self.fee))
            .field("timestamp", &self.timestamp.to_string())
            .field("signature", &hex::encode(&self.signature))
            .finish()
    }
}
impl TransactionA {
    pub fn b(&self) -> TransactionB {
        TransactionB {
            output_address: self.output_address,
            amount: tofuri_int::to_be_bytes(self.amount),
            fee: tofuri_int::to_be_bytes(self.fee),
            timestamp: self.timestamp,
            signature: self.signature,
        }
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    pub fn sign(
        output_address: AddressBytes,
        amount: u128,
        fee: u128,
        timestamp: u32,
        key: &Key,
    ) -> Result<TransactionA, Error> {
        let mut transaction_a = TransactionA {
            input_address: [0; 20],
            output_address,
            amount: tofuri_int::floor(amount),
            fee: tofuri_int::floor(fee),
            timestamp,
            hash: [0; 32],
            signature: [0; 64],
        };
        transaction_a.hash = transaction_a.hash();
        transaction_a.signature = key.sign(&transaction_a.hash).map_err(Error::Key)?;
        transaction_a.input_address = key.address_bytes();
        Ok(transaction_a)
    }
}
impl TransactionB {
    pub fn a(&self, input_address: Option<AddressBytes>) -> Result<TransactionA, Error> {
        let input_address = input_address.unwrap_or(self.input_address()?);
        let transaction_a = TransactionA {
            output_address: self.output_address,
            amount: tofuri_int::from_be_slice(&self.amount),
            fee: tofuri_int::from_be_slice(&self.fee),
            timestamp: self.timestamp,
            signature: self.signature,
            input_address,
            hash: self.hash(),
        };
        Ok(transaction_a)
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    fn input_address(&self) -> Result<AddressBytes, Error> {
        Ok(Key::address(&self.input_public_key()?))
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
fn hash<T: Transaction>(transaction: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(transaction.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Transaction>(transaction: &T) -> [u8; 32] {
    let mut bytes = [0; 32];
    bytes[0..20].copy_from_slice(transaction.get_output_address());
    bytes[20..24].copy_from_slice(&transaction.get_timestamp().to_be_bytes());
    bytes[24..28].copy_from_slice(&transaction.get_amount_bytes());
    bytes[28..32].copy_from_slice(&transaction.get_fee_bytes());
    bytes
}
impl Default for TransactionA {
    fn default() -> TransactionA {
        TransactionA {
            output_address: [0; 20],
            amount: 0,
            fee: 0,
            timestamp: 0,
            signature: [0; 64],
            input_address: [0; 20],
            hash: [0; 32],
        }
    }
}
impl Default for TransactionB {
    fn default() -> TransactionB {
        TransactionB {
            output_address: [0; 20],
            amount: [0; AMOUNT_BYTES],
            fee: [0; AMOUNT_BYTES],
            timestamp: 0,
            signature: [0; 64],
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            TransactionB::default().hash(),
            [
                102, 104, 122, 173, 248, 98, 189, 119, 108, 143, 193, 139, 142, 159, 142, 32, 8,
                151, 20, 133, 110, 226, 51, 179, 144, 42, 89, 29, 13, 95, 41, 37
            ]
        );
    }
}

TransactionA is an expanded version of the transaction that is used primarily for computation purposes. It contains all the necessary information for validating the transaction, such as input and output addresses, transaction amounts, and digital signatures. TransactionA is designed to be comprehensive and detailed, allowing for complex computations and analysis of the transaction data.

On the other hand, TransactionB is a compressed version of the transaction that is used for transmitting over the wire and storing in the database. TransactionB contains a subset of the information present in TransactionA, and it is optimized for storage efficiency and network transmission. It typically includes only the essential information required to validate the transaction, such as input and output addresses, transaction amounts, and transaction fees.

Addresses

Tofuri addresses consist of a total of 50 characters, which can be broken down as follows:

  • The prefix 0x takes up 2 characters.
  • The raw address, which is 20 bytes long, is hex encoded and takes up 40 characters.
  • The checksum, which is 4 bytes long, is hex encoded and takes up 8 characters.

Filename: tofuri/address/src/lib.rs

use sha2::Digest;
use sha2::Sha256;
use tofuri_core::*;
#[derive(Debug)]
pub enum Error {
    Hex(hex::FromHexError),
    InvalidAddress,
    InvalidAddressChecksum,
    AddressChecksumMismatch,
    InvalidSecretKey,
    InvalidSecretKeyChecksum,
    SecretKeyChecksumMismatch,
}
pub fn checksum(bytes: &[u8]) -> [u8; 4] {
    let mut hasher = Sha256::new();
    hasher.update(bytes);
    let hash = hasher.finalize();
    let mut checksum = [0; 4];
    checksum.copy_from_slice(&hash[..4]);
    checksum
}
pub mod address {
    use super::*;
    pub fn encode(address: &AddressBytes) -> String {
        [
            PREFIX_ADDRESS,
            &hex::encode(address),
            &hex::encode(checksum(address)),
        ]
        .concat()
    }
    pub fn decode(str: &str) -> Result<AddressBytes, Error> {
        let decoded = hex::decode(str.replacen(PREFIX_ADDRESS, "", 1)).map_err(Error::Hex)?;
        let address_bytes: AddressBytes = decoded
            .get(0..20)
            .ok_or(Error::InvalidAddress)?
            .try_into()
            .unwrap();
        if checksum(&address_bytes) == decoded.get(20..).ok_or(Error::InvalidAddressChecksum)? {
            Ok(address_bytes)
        } else {
            Err(Error::AddressChecksumMismatch)
        }
    }
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_encode() {
            assert_eq!(
                "0x0000000000000000000000000000000000000000de47c9b2",
                encode(&[0; 20])
            );
        }
        #[test]
        fn test_decode() {
            assert_eq!(
                [0; 20],
                decode("0x0000000000000000000000000000000000000000de47c9b2").unwrap()
            );
        }
    }
}
pub mod secret {
    use super::*;
    pub fn encode(secret_key: &SecretKeyBytes) -> String {
        [
            PREFIX_SECRET_KEY,
            &hex::encode(secret_key),
            &hex::encode(checksum(secret_key)),
        ]
        .concat()
    }
    pub fn decode(str: &str) -> Result<SecretKeyBytes, Error> {
        let decoded = hex::decode(str.replacen(PREFIX_SECRET_KEY, "", 1)).map_err(Error::Hex)?;
        let secret_key_bytes: SecretKeyBytes = decoded
            .get(0..32)
            .ok_or(Error::InvalidSecretKey)?
            .try_into()
            .unwrap();
        if checksum(&secret_key_bytes)
            == decoded.get(32..).ok_or(Error::InvalidSecretKeyChecksum)?
        {
            Ok(secret_key_bytes)
        } else {
            Err(Error::SecretKeyChecksumMismatch)
        }
    }
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_encode() {
            assert_eq!(
                encode(&[0; 32]),
                "SECRETx000000000000000000000000000000000000000000000000000000000000000066687aad"
            );
        }
        #[test]
        fn test_decode() {
            assert_eq!(
                decode("SECRETx000000000000000000000000000000000000000000000000000000000000000066687aad").unwrap(),
                [0; 32]
            );
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_cecksum() {
        assert_eq!(checksum(&[0; 32]), [102, 104, 122, 173]);
        assert_eq!(checksum(&[0; 33]), [127, 156, 158, 49]);
    }
}

Checksum

Tofuri addresses are designed to mitigate the risks of typographical errors that can lead to the loss of funds. To achieve this, a hash checksum of 4 bytes is added to the end of each address. This additional layer of security ensures that even if an incorrect address is mistakenly entered, the checksum validation process will prevent it from being accepted as a valid address. As a result, the probability of an incorrect address being accepted is greatly reduced, with a probability of 1 in 4,294,967,296.

By including a checksum, Tofuri addresses help prevent the accidental sending of funds to non-existent or incorrect addresses due to typos or other errors. This enhances the overall security and reliability of the system, ensuring that transactions are executed smoothly and without any mishaps.

If you ever happen to misstype an address and still have the checksum accept it as valid, you can either feel lucky, or start questioning the randomness of the universe!

Filename: tofuri/address/src/lib.rs

use sha2::Digest;
use sha2::Sha256;
use tofuri_core::*;
#[derive(Debug)]
pub enum Error {
    Hex(hex::FromHexError),
    InvalidAddress,
    InvalidAddressChecksum,
    AddressChecksumMismatch,
    InvalidSecretKey,
    InvalidSecretKeyChecksum,
    SecretKeyChecksumMismatch,
}
pub fn checksum(bytes: &[u8]) -> [u8; 4] {
    let mut hasher = Sha256::new();
    hasher.update(bytes);
    let hash = hasher.finalize();
    let mut checksum = [0; 4];
    checksum.copy_from_slice(&hash[..4]);
    checksum
}
pub mod address {
    use super::*;
    pub fn encode(address: &AddressBytes) -> String {
        [
            PREFIX_ADDRESS,
            &hex::encode(address),
            &hex::encode(checksum(address)),
        ]
        .concat()
    }
    pub fn decode(str: &str) -> Result<AddressBytes, Error> {
        let decoded = hex::decode(str.replacen(PREFIX_ADDRESS, "", 1)).map_err(Error::Hex)?;
        let address_bytes: AddressBytes = decoded
            .get(0..20)
            .ok_or(Error::InvalidAddress)?
            .try_into()
            .unwrap();
        if checksum(&address_bytes) == decoded.get(20..).ok_or(Error::InvalidAddressChecksum)? {
            Ok(address_bytes)
        } else {
            Err(Error::AddressChecksumMismatch)
        }
    }
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_encode() {
            assert_eq!(
                "0x0000000000000000000000000000000000000000de47c9b2",
                encode(&[0; 20])
            );
        }
        #[test]
        fn test_decode() {
            assert_eq!(
                [0; 20],
                decode("0x0000000000000000000000000000000000000000de47c9b2").unwrap()
            );
        }
    }
}
pub mod secret {
    use super::*;
    pub fn encode(secret_key: &SecretKeyBytes) -> String {
        [
            PREFIX_SECRET_KEY,
            &hex::encode(secret_key),
            &hex::encode(checksum(secret_key)),
        ]
        .concat()
    }
    pub fn decode(str: &str) -> Result<SecretKeyBytes, Error> {
        let decoded = hex::decode(str.replacen(PREFIX_SECRET_KEY, "", 1)).map_err(Error::Hex)?;
        let secret_key_bytes: SecretKeyBytes = decoded
            .get(0..32)
            .ok_or(Error::InvalidSecretKey)?
            .try_into()
            .unwrap();
        if checksum(&secret_key_bytes)
            == decoded.get(32..).ok_or(Error::InvalidSecretKeyChecksum)?
        {
            Ok(secret_key_bytes)
        } else {
            Err(Error::SecretKeyChecksumMismatch)
        }
    }
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_encode() {
            assert_eq!(
                encode(&[0; 32]),
                "SECRETx000000000000000000000000000000000000000000000000000000000000000066687aad"
            );
        }
        #[test]
        fn test_decode() {
            assert_eq!(
                decode("SECRETx000000000000000000000000000000000000000000000000000000000000000066687aad").unwrap(),
                [0; 32]
            );
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_cecksum() {
        assert_eq!(checksum(&[0; 32]), [102, 104, 122, 173]);
        assert_eq!(checksum(&[0; 33]), [127, 156, 158, 49]);
    }
}

Secret keys

Secret keys are encoded with the prefix SECRETx and are longer than Tofuri addresses. A Tofuri secret key consists of a total of 79 characters, which can be broken down as follows:

  • The prefix SECRETx takes up 7 characters.
  • The secret key, which is 32 bytes long, is hex encoded and takes up 64 characters.
  • The checksum, which is 4 bytes long, is hex encoded and takes up 8 characters.

It's also important to remember that if a secret key is lost or stolen, it can result in the permanent loss of associated funds. Therefore, it's crucial to keep secret keys safe and secure.

Filename: tofuri/address/src/lib.rs

use sha2::Digest;
use sha2::Sha256;
use tofuri_core::*;
#[derive(Debug)]
pub enum Error {
    Hex(hex::FromHexError),
    InvalidAddress,
    InvalidAddressChecksum,
    AddressChecksumMismatch,
    InvalidSecretKey,
    InvalidSecretKeyChecksum,
    SecretKeyChecksumMismatch,
}
pub fn checksum(bytes: &[u8]) -> [u8; 4] {
    let mut hasher = Sha256::new();
    hasher.update(bytes);
    let hash = hasher.finalize();
    let mut checksum = [0; 4];
    checksum.copy_from_slice(&hash[..4]);
    checksum
}
pub mod address {
    use super::*;
    pub fn encode(address: &AddressBytes) -> String {
        [
            PREFIX_ADDRESS,
            &hex::encode(address),
            &hex::encode(checksum(address)),
        ]
        .concat()
    }
    pub fn decode(str: &str) -> Result<AddressBytes, Error> {
        let decoded = hex::decode(str.replacen(PREFIX_ADDRESS, "", 1)).map_err(Error::Hex)?;
        let address_bytes: AddressBytes = decoded
            .get(0..20)
            .ok_or(Error::InvalidAddress)?
            .try_into()
            .unwrap();
        if checksum(&address_bytes) == decoded.get(20..).ok_or(Error::InvalidAddressChecksum)? {
            Ok(address_bytes)
        } else {
            Err(Error::AddressChecksumMismatch)
        }
    }
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_encode() {
            assert_eq!(
                "0x0000000000000000000000000000000000000000de47c9b2",
                encode(&[0; 20])
            );
        }
        #[test]
        fn test_decode() {
            assert_eq!(
                [0; 20],
                decode("0x0000000000000000000000000000000000000000de47c9b2").unwrap()
            );
        }
    }
}
pub mod secret {
    use super::*;
    pub fn encode(secret_key: &SecretKeyBytes) -> String {
        [
            PREFIX_SECRET_KEY,
            &hex::encode(secret_key),
            &hex::encode(checksum(secret_key)),
        ]
        .concat()
    }
    pub fn decode(str: &str) -> Result<SecretKeyBytes, Error> {
        let decoded = hex::decode(str.replacen(PREFIX_SECRET_KEY, "", 1)).map_err(Error::Hex)?;
        let secret_key_bytes: SecretKeyBytes = decoded
            .get(0..32)
            .ok_or(Error::InvalidSecretKey)?
            .try_into()
            .unwrap();
        if checksum(&secret_key_bytes)
            == decoded.get(32..).ok_or(Error::InvalidSecretKeyChecksum)?
        {
            Ok(secret_key_bytes)
        } else {
            Err(Error::SecretKeyChecksumMismatch)
        }
    }
    #[cfg(test)]
    mod tests {
        use super::*;
        #[test]
        fn test_encode() {
            assert_eq!(
                encode(&[0; 32]),
                "SECRETx000000000000000000000000000000000000000000000000000000000000000066687aad"
            );
        }
        #[test]
        fn test_decode() {
            assert_eq!(
                decode("SECRETx000000000000000000000000000000000000000000000000000000000000000066687aad").unwrap(),
                [0; 32]
            );
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_cecksum() {
        assert_eq!(checksum(&[0; 32]), [102, 104, 122, 173]);
        assert_eq!(checksum(&[0; 33]), [127, 156, 158, 49]);
    }
}

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) -> &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);
    }
}
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);
    }
}

Stakes

Stakes are a means for a node to explicitly express its willingness to assume the role of a validator within the network. A stake consists of a deposit or withdrawal from an account and can consist of any amount x of stake.

Filename: tofuri/stake/src/lib.rs

use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_address::address;
use tofuri_core::*;
use tofuri_key::Key;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
}
pub trait Stake {
    fn get_timestamp(&self) -> u32;
    fn get_deposit(&self) -> bool;
    fn get_fee_bytes(&self) -> AmountBytes;
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 9];
}
impl Stake for StakeA {
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_deposit(&self) -> bool {
        self.deposit
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        tofuri_int::to_be_bytes(self.fee)
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 9] {
        hash_input(self)
    }
}
impl Stake for StakeB {
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_deposit(&self) -> bool {
        self.deposit
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        self.fee
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 9] {
        hash_input(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct StakeA {
    pub amount: u128,
    pub fee: u128,
    pub deposit: bool,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    pub input_address: AddressBytes,
    pub hash: Hash,
}
impl fmt::Debug for StakeA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("StakeA")
            .field("amount", &tofuri_int::to_string(self.amount))
            .field("fee", &tofuri_int::to_string(self.fee))
            .field("deposit", &self.deposit)
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("input_address", &address::encode(&self.input_address))
            .field("hash", &hex::encode(&self.hash))
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct StakeB {
    pub amount: AmountBytes,
    pub fee: AmountBytes,
    pub deposit: bool,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
}
impl fmt::Debug for StakeB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("StakeB")
            .field("amount", &hex::encode(&self.amount))
            .field("fee", &hex::encode(&self.fee))
            .field("deposit", &self.deposit)
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .finish()
    }
}
impl StakeA {
    pub fn b(&self) -> StakeB {
        StakeB {
            amount: tofuri_int::to_be_bytes(self.amount),
            fee: tofuri_int::to_be_bytes(self.fee),
            deposit: self.deposit,
            timestamp: self.timestamp,
            signature: self.signature,
        }
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    pub fn sign(
        deposit: bool,
        amount: u128,
        fee: u128,
        timestamp: u32,
        key: &Key,
    ) -> Result<StakeA, Error> {
        let mut stake_a = StakeA {
            amount: tofuri_int::floor(amount),
            fee: tofuri_int::floor(fee),
            deposit,
            timestamp,
            signature: [0; 64],
            input_address: [0; 20],
            hash: [0; 32],
        };
        stake_a.hash = stake_a.hash();
        stake_a.signature = key.sign(&stake_a.hash).map_err(Error::Key)?;
        stake_a.input_address = key.address_bytes();
        Ok(stake_a)
    }
}
impl StakeB {
    pub fn a(&self, input_address: Option<AddressBytes>) -> Result<StakeA, Error> {
        let input_address = input_address.unwrap_or(self.input_address()?);
        let stake_a = StakeA {
            amount: tofuri_int::from_be_slice(&self.amount),
            fee: tofuri_int::from_be_slice(&self.fee),
            deposit: self.deposit,
            timestamp: self.timestamp,
            signature: self.signature,
            input_address,
            hash: self.hash(),
        };
        Ok(stake_a)
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    fn input_address(&self) -> Result<AddressBytes, Error> {
        let input_address = Key::address(&self.input_public_key()?);
        Ok(input_address)
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
fn hash<T: Stake>(stake: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(stake.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Stake>(stake: &T) -> [u8; 9] {
    let mut bytes = [0; 9];
    bytes[0..4].copy_from_slice(&stake.get_timestamp().to_be_bytes());
    bytes[4..8].copy_from_slice(&stake.get_fee_bytes());
    bytes[8] = if stake.get_deposit() { 1 } else { 0 };
    bytes
}
impl Default for StakeA {
    fn default() -> StakeA {
        StakeA {
            amount: 0,
            fee: 0,
            deposit: false,
            timestamp: 0,
            signature: [0; 64],
            input_address: [0; 20],
            hash: [0; 32],
        }
    }
}
impl Default for StakeB {
    fn default() -> StakeB {
        StakeB {
            amount: [0; AMOUNT_BYTES],
            fee: [0; AMOUNT_BYTES],
            deposit: false,
            timestamp: 0,
            signature: [0; 64],
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            StakeB::default().hash(),
            [
                62, 112, 119, 253, 47, 102, 214, 137, 224, 206, 230, 167, 207, 91, 55, 191, 45,
                202, 124, 151, 154, 243, 86, 208, 163, 28, 188, 92, 133, 96, 92, 125
            ]
        );
    }
}
use serde::Deserialize;
use serde::Serialize;
use serde_big_array::BigArray;
use sha2::Digest;
use sha2::Sha256;
use std::fmt;
use tofuri_address::address;
use tofuri_core::*;
use tofuri_key::Key;
#[derive(Debug)]
pub enum Error {
    Key(tofuri_key::Error),
}
pub trait Stake {
    fn get_timestamp(&self) -> u32;
    fn get_deposit(&self) -> bool;
    fn get_fee_bytes(&self) -> AmountBytes;
    fn hash(&self) -> Hash;
    fn hash_input(&self) -> [u8; 9];
}
impl Stake for StakeA {
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_deposit(&self) -> bool {
        self.deposit
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        tofuri_int::to_be_bytes(self.fee)
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 9] {
        hash_input(self)
    }
}
impl Stake for StakeB {
    fn get_timestamp(&self) -> u32 {
        self.timestamp
    }
    fn get_deposit(&self) -> bool {
        self.deposit
    }
    fn get_fee_bytes(&self) -> AmountBytes {
        self.fee
    }
    fn hash(&self) -> Hash {
        hash(self)
    }
    fn hash_input(&self) -> [u8; 9] {
        hash_input(self)
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct StakeA {
    pub amount: u128,
    pub fee: u128,
    pub deposit: bool,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
    pub input_address: AddressBytes,
    pub hash: Hash,
}
impl fmt::Debug for StakeA {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("StakeA")
            .field("amount", &tofuri_int::to_string(self.amount))
            .field("fee", &tofuri_int::to_string(self.fee))
            .field("deposit", &self.deposit)
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .field("input_address", &address::encode(&self.input_address))
            .field("hash", &hex::encode(&self.hash))
            .finish()
    }
}
#[derive(Serialize, Deserialize, Clone)]
pub struct StakeB {
    pub amount: AmountBytes,
    pub fee: AmountBytes,
    pub deposit: bool,
    pub timestamp: u32,
    #[serde(with = "BigArray")]
    pub signature: SignatureBytes,
}
impl fmt::Debug for StakeB {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        f.debug_struct("StakeB")
            .field("amount", &hex::encode(&self.amount))
            .field("fee", &hex::encode(&self.fee))
            .field("deposit", &self.deposit)
            .field("timestamp", &self.timestamp)
            .field("signature", &hex::encode(&self.signature))
            .finish()
    }
}
impl StakeA {
    pub fn b(&self) -> StakeB {
        StakeB {
            amount: tofuri_int::to_be_bytes(self.amount),
            fee: tofuri_int::to_be_bytes(self.fee),
            deposit: self.deposit,
            timestamp: self.timestamp,
            signature: self.signature,
        }
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    pub fn sign(
        deposit: bool,
        amount: u128,
        fee: u128,
        timestamp: u32,
        key: &Key,
    ) -> Result<StakeA, Error> {
        let mut stake_a = StakeA {
            amount: tofuri_int::floor(amount),
            fee: tofuri_int::floor(fee),
            deposit,
            timestamp,
            signature: [0; 64],
            input_address: [0; 20],
            hash: [0; 32],
        };
        stake_a.hash = stake_a.hash();
        stake_a.signature = key.sign(&stake_a.hash).map_err(Error::Key)?;
        stake_a.input_address = key.address_bytes();
        Ok(stake_a)
    }
}
impl StakeB {
    pub fn a(&self, input_address: Option<AddressBytes>) -> Result<StakeA, Error> {
        let input_address = input_address.unwrap_or(self.input_address()?);
        let stake_a = StakeA {
            amount: tofuri_int::from_be_slice(&self.amount),
            fee: tofuri_int::from_be_slice(&self.fee),
            deposit: self.deposit,
            timestamp: self.timestamp,
            signature: self.signature,
            input_address,
            hash: self.hash(),
        };
        Ok(stake_a)
    }
    pub fn hash(&self) -> Hash {
        hash(self)
    }
    fn input_address(&self) -> Result<AddressBytes, Error> {
        let input_address = Key::address(&self.input_public_key()?);
        Ok(input_address)
    }
    fn input_public_key(&self) -> Result<PublicKeyBytes, Error> {
        Key::recover(&self.hash(), &self.signature).map_err(Error::Key)
    }
}
fn hash<T: Stake>(stake: &T) -> Hash {
    let mut hasher = Sha256::new();
    hasher.update(stake.hash_input());
    hasher.finalize().into()
}
fn hash_input<T: Stake>(stake: &T) -> [u8; 9] {
    let mut bytes = [0; 9];
    bytes[0..4].copy_from_slice(&stake.get_timestamp().to_be_bytes());
    bytes[4..8].copy_from_slice(&stake.get_fee_bytes());
    bytes[8] = if stake.get_deposit() { 1 } else { 0 };
    bytes
}
impl Default for StakeA {
    fn default() -> StakeA {
        StakeA {
            amount: 0,
            fee: 0,
            deposit: false,
            timestamp: 0,
            signature: [0; 64],
            input_address: [0; 20],
            hash: [0; 32],
        }
    }
}
impl Default for StakeB {
    fn default() -> StakeB {
        StakeB {
            amount: [0; AMOUNT_BYTES],
            fee: [0; AMOUNT_BYTES],
            deposit: false,
            timestamp: 0,
            signature: [0; 64],
        }
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_hash() {
        assert_eq!(
            StakeB::default().hash(),
            [
                62, 112, 119, 253, 47, 102, 214, 137, 224, 206, 230, 167, 207, 91, 55, 191, 45,
                202, 124, 151, 154, 243, 86, 208, 163, 28, 188, 92, 133, 96, 92, 125
            ]
        );
    }
}

StakeA is the expanded version of the stake stake, and it contains all the necessary information for validating the stake.

On the other hand, StakeB is the compressed version of the stake stake, and it is optimized for storage efficiency and network transmission.

Large Integer Representation

Tofuri has created a specialized integer data type that has the ability to store very large numbers with fixed precision, while minimizing storage usage. This custom integer is designed to efficiently represent values with high precision, using a smaller amount of memory.

The custom integer operates by dividing the number into smaller integers, each representing a specific digit or group of digits. These smaller integers are then saved in a fixed-size array, with each array element representing a specific digit or group of digits in the larger number.

By adopting this approach, Tofuri is able to save large numbers with high precision using a relatively small amount of memory. This is because the custom integer only stores the necessary digits, rather than reserving memory for all possible digits, as is common with traditional integer data types.

Filename: tofuri/int/src/lib.rs

use std::num::ParseIntError;
use tofuri_core::*;
#[derive(Debug)]
pub enum Error {
    FromStr(ParseIntError),
}
pub fn to_be_bytes(uint: u128) -> AmountBytes {
    if uint == 0 {
        return [0; AMOUNT_BYTES];
    }
    let bytes = uint.to_be_bytes();
    let mut i = 0;
    for byte in bytes {
        if byte != 0 {
            break;
        }
        i += 1;
    }
    let size = 15 - i;
    let mut output = [0; AMOUNT_BYTES];
    for (j, v) in output.iter_mut().enumerate().take(AMOUNT_BYTES) {
        let k = i + j;
        if k == 16 {
            break;
        }
        *v = bytes[k];
    }
    output[AMOUNT_BYTES - 1] = (output[AMOUNT_BYTES - 1] & 0xf0) | size as u8;
    output
}
pub fn from_be_slice(slice: &[u8; AMOUNT_BYTES]) -> u128 {
    let size = slice[AMOUNT_BYTES - 1] as usize & 0x0f;
    let mut bytes = [0; 16];
    for (i, v) in slice.iter().enumerate().take(AMOUNT_BYTES) {
        let j = 15 - size + i;
        if j == 16 {
            break;
        }
        if i == AMOUNT_BYTES - 1 {
            bytes[j] = v & 0xf0;
            break;
        }
        bytes[j] = *v;
    }
    u128::from_be_bytes(bytes)
}
pub fn floor(uint: u128) -> u128 {
    from_be_slice(&to_be_bytes(uint))
}
pub fn to_string(uint: u128) -> String {
    let mut string = format!("{}{}", "0".repeat(DECIMAL_PLACES), uint);
    string.insert(string.len() - DECIMAL_PLACES, '.');
    string = string
        .trim_start_matches('0')
        .trim_end_matches('0')
        .trim_end_matches('.')
        .to_string();
    if string.starts_with('.') {
        let mut s = "0".to_string();
        s.push_str(&string);
        string = s;
    }
    if string.is_empty() {
        string.push('0');
    }
    string
}
pub fn from_str(str: &str) -> Result<u128, Error> {
    let (mut string, diff) = match str.split_once('.') {
        Some((a, b)) => {
            let mut string = a.to_string();
            string.push_str(b);
            (string, DECIMAL_PLACES - b.len())
        }
        None => (str.to_string(), DECIMAL_PLACES),
    };
    string.push_str(&"0".repeat(diff));
    string.parse().map_err(Error::FromStr)
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test_encode() {
        assert_eq!([1, 0, 0, 8], to_be_bytes(0x10000000000000000));
    }
    #[test]
    fn test_decode() {
        assert_eq!(0x10000000000000000, from_be_slice(&[1, 0, 0, 8]));
    }
    #[test]
    fn test_decode_max() {
        assert_eq!(
            0xfffffff0000000000000000000000000,
            from_be_slice(&[0xff, 0xff, 0xff, 0xff])
        );
    }
    #[test]
    fn test_to_string() {
        assert_eq!("10.01", to_string(10_010_000_000_000_000_000));
        assert_eq!("1", to_string(1_000_000_000_000_000_000));
        assert_eq!("10", to_string(10_000_000_000_000_000_000));
        assert_eq!("0.1", to_string(100_000_000_000_000_000));
        assert_eq!("0", to_string(0));
    }
    #[test]
    fn test_from_string() {
        assert_eq!(10_010_000_000_000_000_000, from_str("010.010").unwrap());
        assert_eq!(1_000_000_000_000_000_000, from_str("1").unwrap());
        assert_eq!(10_000_000_000_000_000_000, from_str("10").unwrap());
        assert_eq!(10_000_000_000_000_000_000, from_str("10.").unwrap());
        assert_eq!(10_000_000_000_000_000_000, from_str("10.0").unwrap());
        assert_eq!(100_000_000_000_000_000, from_str(".1").unwrap());
        assert_eq!(0, from_str("0").unwrap());
    }
}

Database

Tofuri has chosen to use RocksDB as the database for storing the blockchain for various reasons. The first reason is that RocksDB is optimized for fast data access, making it an ideal option for storing large amounts of data with low latency, like the blockchain. Additionally, the ability of RocksDB to handle vast amounts of data and provide reliable storage is crucial for storing the expanding blockchain, which needs a secure and scalable storage solution.

Networking

Tofuri has chosen to use libp2p for all its node-to-node network communication.

Libp2p is a modular networking library designed to provide a peer-to-peer networking stack, making it easy for developers to create decentralized applications. Its secure and decentralized networking capability is one of its key strengths.

Cryptography

Tofuri is a cryptocurrency that utilizes several cryptographic algorithms to ensure security and integrity in its transactions.

Proof of Stake (PoS)

Proof of Stake is a consensus algorithm used by Tofuri to validate transactions on its blockchain network. It replaces the Proof of Work (PoW) algorithm used by Bitcoin and other cryptocurrencies. PoS allows validators to participate in the creation and validation of new blocks based on the amount of cryptocurrency they hold in their wallets.

This system incentivizes validators to act in the best interest of the network by holding onto their tokens, preventing malicious behavior, and promoting network stability.

Secp256k1

Secp256k1 is an elliptic curve cryptography algorithm used by Tofuri to secure its transactions. It is the same algorithm used by Bitcoin and is well-known for its efficiency and security. Secp256k1 ensures that transactions are secure and cannot be tampered with by a third party.

Read more: https://bitcoin.it/wiki/Secp256k1.

SHA-2

SHA-2 is a family of cryptographic hash functions used by Tofuri to hash data in its transactions. This algorithm ensures that data cannot be altered without detection. SHA-2 is considered to be secure and is widely used in many cryptographic applications.

Read more: https://wikipedia.org/wiki/SHA-2.

Verifiable Random Functions (VRF)

Verifiable Random Functions (VRF) is a cryptographic algorithm used by Tofuri to select validators for block creation. It ensures that the selection process is random and cannot be manipulated. VRF also provides a way for validators to prove that they were selected fairly.

Read more: https://wikipedia.org/wiki/Verifiable_random_function.

Conclusion

Tofuri's use of PoS, Secp256k1, SHA-2, and VRF ensures that its blockchain network is secure, efficient, and reliable. These cryptographic algorithms work together to prevent malicious behavior, promote network stability, and ensure the integrity of its transactions.

Blockchain

Blockchain is a distributed ledger technology that serves as the foundation for many cryptocurrencies, including Tofuri. At its core, a blockchain is a continuously growing list of records, called blocks, which are linked and secured using cryptography.

Each block in a blockchain contains a cryptographic hash of the previous block, a timestamp, and transaction data. This creates an immutable chain of blocks that cannot be altered once they have been added to the blockchain. Because of this, blockchains provide a high level of security and transparency, making them ideal for use in financial systems.

In the case of Tofuri, the blockchain is maintained by a network of nodes, each of which has a copy of the blockchain. When a new transaction is initiated, it is broadcast to the network and verified by the nodes using a consensus algorithm. Once a transaction is verified, it is added to a block, which is then added to the blockchain.

Because the blockchain is decentralized and distributed, it is resistant to tampering and hacking. Additionally, because the blockchain is transparent, users can view all transactions that have occurred on the network, providing an additional layer of security.

Overall, blockchain technology is a revolutionary way to securely and transparently manage transactions and data, and it forms the backbone of Tofuri's cryptocurrency system.

Tree

This documentation describes the implementation of a blockchain tree data structure in Rust. A blockchain tree is a variation of a blockchain that allows for multiple branches to coexist and compete with each other.

Filename: tofuri/tree/src/lib.rs

use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt;
use tofuri_core::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Branch {
    pub hash: Hash,
    pub height: usize,
    pub timestamp: u32,
}
impl fmt::Display for Branch {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Branch {{ hash: {}, height: {}, timestamp: {} }}",
            hex::encode(&self.hash),
            self.height,
            self.timestamp
        )
    }
}
impl Branch {
    fn new(hash: Hash, height: usize, timestamp: u32) -> Branch {
        Branch {
            hash,
            height,
            timestamp,
        }
    }
}
#[derive(Default, Debug, Clone)]
pub struct Tree {
    branches: Vec<Branch>,
    hashes: HashMap<Hash, Hash>,
}
impl fmt::Display for Tree {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut s = String::new();
        s.push_str("Tree {\n");
        s.push_str("  branches: [\n");
        for branch in &self.branches {
            s.push_str(&format!("    {},\n", branch));
        }
        s.push_str("  ],\n");
        s.push_str("  hashes: {\n");
        for (key, value) in &self.hashes {
            s.push_str(&format!(
                "    {}: {},\n",
                hex::encode(key),
                hex::encode(value)
            ));
        }
        s.push_str("  }\n}");
        write!(f, "{}", s)
    }
}
impl Tree {
    pub fn main(&self) -> Option<&Branch> {
        self.branches.first()
    }
    pub fn size(&self) -> usize {
        self.hashes.len()
    }
    pub fn stable_and_unstable_hashes(
        &self,
        trust_fork_after_blocks: usize,
    ) -> (Vec<Hash>, Vec<Hash>) {
        let mut stable_hashes = vec![];
        if let Some(main) = self.main() {
            let mut hash = main.hash;
            loop {
                stable_hashes.push(hash);
                match self.get(&hash) {
                    Some(previous_hash) => hash = *previous_hash,
                    None => break,
                };
            }
        }
        if let Some(hash) = stable_hashes.last() {
            if hash != &GENESIS_BLOCK_PREVIOUS_HASH {
                panic!("broken chain")
            }
            stable_hashes.pop();
        }
        stable_hashes.reverse();
        let len = stable_hashes.len();
        let start = if len < trust_fork_after_blocks {
            0
        } else {
            len - trust_fork_after_blocks
        };
        let unstable_hashes = stable_hashes.drain(start..len).collect();
        (stable_hashes, unstable_hashes)
    }
    pub fn unstable_hashes(&self, trust_fork_after_blocks: usize) -> Vec<Hash> {
        let mut vec = vec![];
        if let Some(main) = self.main() {
            let mut hash = main.hash;
            for _ in 0..trust_fork_after_blocks {
                vec.push(hash);
                match self.get(&hash) {
                    Some(previous_hash) => hash = *previous_hash,
                    None => break,
                };
            }
        }
        if let Some(hash) = vec.last() {
            if hash == &GENESIS_BLOCK_PREVIOUS_HASH {
                vec.pop();
            }
        }
        vec.reverse();
        vec
    }
    pub fn get(&self, hash: &Hash) -> Option<&Hash> {
        self.hashes.get(hash)
    }
    pub fn insert(&mut self, hash: Hash, previous_hash: Hash, timestamp: u32) -> bool {
        if self.hashes.insert(hash, previous_hash).is_some() {
            panic!("hash collision");
        }
        if let Some(index) = self.branches.iter().position(|a| a.hash == previous_hash) {
            self.branches[index] = Branch::new(hash, self.branches[index].height + 1, timestamp);
            return false;
        }
        self.branches
            .push(Branch::new(hash, self.height(&previous_hash), timestamp));
        true
    }
    pub fn sort_branches(&mut self) {
        self.branches.sort_by(|a, b| {
            match b.height.cmp(&a.height) {
                Ordering::Equal => {}
                x => return x,
            }
            match a.timestamp.cmp(&b.timestamp) {
                Ordering::Equal => {}
                x => return x,
            }
            a.hash.cmp(&b.hash)
        });
    }
    pub fn clear(&mut self) {
        self.branches.clear();
        self.hashes.clear();
    }
    fn height(&self, previous_hash: &Hash) -> usize {
        let mut hash = previous_hash;
        let mut height = 0;
        loop {
            match self.hashes.get(hash) {
                Some(previous_hash) => {
                    hash = previous_hash;
                    height += 1;
                }
                None => {
                    if hash != &[0; 32] {
                        panic!("broken chain")
                    }
                    break;
                }
            };
        }
        height
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test() {
        let mut tree = Tree::default();
        tree.insert([0x11; 32], [0x00; 32], 1);
        tree.insert([0x22; 32], [0x11; 32], 1);
        tree.insert([0x33; 32], [0x22; 32], 1);
        assert_eq!(tree.size(), 3);
        tree.insert([0x44; 32], [0x33; 32], 1);
        tree.insert([0x55; 32], [0x22; 32], 1);
        tree.insert([0x66; 32], [0x00; 32], 1);
        tree.insert([0x77; 32], [0x55; 32], 0);
        tree.insert([0x88; 32], [0x55; 32], 0);
        assert_eq!(tree.main(), Some(&Branch::new([0x44; 32], 3, 1)));
        tree.sort_branches();
        assert_eq!(tree.main(), Some(&Branch::new([0x77; 32], 3, 0)));
        assert_eq!(tree.size(), 8);
    }
}
use std::cmp::Ordering;
use std::collections::HashMap;
use std::fmt;
use tofuri_core::*;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct Branch {
    pub hash: Hash,
    pub height: usize,
    pub timestamp: u32,
}
impl fmt::Display for Branch {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        write!(
            f,
            "Branch {{ hash: {}, height: {}, timestamp: {} }}",
            hex::encode(&self.hash),
            self.height,
            self.timestamp
        )
    }
}
impl Branch {
    fn new(hash: Hash, height: usize, timestamp: u32) -> Branch {
        Branch {
            hash,
            height,
            timestamp,
        }
    }
}
#[derive(Default, Debug, Clone)]
pub struct Tree {
    branches: Vec<Branch>,
    hashes: HashMap<Hash, Hash>,
}
impl fmt::Display for Tree {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        let mut s = String::new();
        s.push_str("Tree {\n");
        s.push_str("  branches: [\n");
        for branch in &self.branches {
            s.push_str(&format!("    {},\n", branch));
        }
        s.push_str("  ],\n");
        s.push_str("  hashes: {\n");
        for (key, value) in &self.hashes {
            s.push_str(&format!(
                "    {}: {},\n",
                hex::encode(key),
                hex::encode(value)
            ));
        }
        s.push_str("  }\n}");
        write!(f, "{}", s)
    }
}
impl Tree {
    pub fn main(&self) -> Option<&Branch> {
        self.branches.first()
    }
    pub fn size(&self) -> usize {
        self.hashes.len()
    }
    pub fn stable_and_unstable_hashes(
        &self,
        trust_fork_after_blocks: usize,
    ) -> (Vec<Hash>, Vec<Hash>) {
        let mut stable_hashes = vec![];
        if let Some(main) = self.main() {
            let mut hash = main.hash;
            loop {
                stable_hashes.push(hash);
                match self.get(&hash) {
                    Some(previous_hash) => hash = *previous_hash,
                    None => break,
                };
            }
        }
        if let Some(hash) = stable_hashes.last() {
            if hash != &GENESIS_BLOCK_PREVIOUS_HASH {
                panic!("broken chain")
            }
            stable_hashes.pop();
        }
        stable_hashes.reverse();
        let len = stable_hashes.len();
        let start = if len < trust_fork_after_blocks {
            0
        } else {
            len - trust_fork_after_blocks
        };
        let unstable_hashes = stable_hashes.drain(start..len).collect();
        (stable_hashes, unstable_hashes)
    }
    pub fn unstable_hashes(&self, trust_fork_after_blocks: usize) -> Vec<Hash> {
        let mut vec = vec![];
        if let Some(main) = self.main() {
            let mut hash = main.hash;
            for _ in 0..trust_fork_after_blocks {
                vec.push(hash);
                match self.get(&hash) {
                    Some(previous_hash) => hash = *previous_hash,
                    None => break,
                };
            }
        }
        if let Some(hash) = vec.last() {
            if hash == &GENESIS_BLOCK_PREVIOUS_HASH {
                vec.pop();
            }
        }
        vec.reverse();
        vec
    }
    pub fn get(&self, hash: &Hash) -> Option<&Hash> {
        self.hashes.get(hash)
    }
    pub fn insert(&mut self, hash: Hash, previous_hash: Hash, timestamp: u32) -> bool {
        if self.hashes.insert(hash, previous_hash).is_some() {
            panic!("hash collision");
        }
        if let Some(index) = self.branches.iter().position(|a| a.hash == previous_hash) {
            self.branches[index] = Branch::new(hash, self.branches[index].height + 1, timestamp);
            return false;
        }
        self.branches
            .push(Branch::new(hash, self.height(&previous_hash), timestamp));
        true
    }
    pub fn sort_branches(&mut self) {
        self.branches.sort_by(|a, b| {
            match b.height.cmp(&a.height) {
                Ordering::Equal => {}
                x => return x,
            }
            match a.timestamp.cmp(&b.timestamp) {
                Ordering::Equal => {}
                x => return x,
            }
            a.hash.cmp(&b.hash)
        });
    }
    pub fn clear(&mut self) {
        self.branches.clear();
        self.hashes.clear();
    }
    fn height(&self, previous_hash: &Hash) -> usize {
        let mut hash = previous_hash;
        let mut height = 0;
        loop {
            match self.hashes.get(hash) {
                Some(previous_hash) => {
                    hash = previous_hash;
                    height += 1;
                }
                None => {
                    if hash != &[0; 32] {
                        panic!("broken chain")
                    }
                    break;
                }
            };
        }
        height
    }
}
#[cfg(test)]
mod tests {
    use super::*;
    #[test]
    fn test() {
        let mut tree = Tree::default();
        tree.insert([0x11; 32], [0x00; 32], 1);
        tree.insert([0x22; 32], [0x11; 32], 1);
        tree.insert([0x33; 32], [0x22; 32], 1);
        assert_eq!(tree.size(), 3);
        tree.insert([0x44; 32], [0x33; 32], 1);
        tree.insert([0x55; 32], [0x22; 32], 1);
        tree.insert([0x66; 32], [0x00; 32], 1);
        tree.insert([0x77; 32], [0x55; 32], 0);
        tree.insert([0x88; 32], [0x55; 32], 0);
        assert_eq!(tree.main(), Some(&Branch::new([0x44; 32], 3, 1)));
        tree.sort_branches();
        assert_eq!(tree.main(), Some(&Branch::new([0x77; 32], 3, 0)));
        assert_eq!(tree.size(), 8);
    }
}

The Tree struct contains two main components: a vector of Branch structs and a HashMap that maps each block's hash to its previous block's hash. Each Branch represents a distinct branch of the blockchain, with a hash representing the most recent block in the branch, a height indicating the number of blocks in the branch, and a timestamp representing the time of the most recent block in the branch.

The Tree struct provides several methods for manipulating the blockchain tree. The insert method allows for new blocks to be added to the tree, with the option to specify a timestamp for each block. If a new block has the same hash as an existing block, the method will panic, since each block in the blockchain should have a unique hash.

The sort_branches method is used to sort the branches in the tree, with the branch having the highest height and most recent timestamp being placed at the front of the branches vector. This method is important because it determines which branch is considered the "main" branch of the blockchain, which is used as the basis for determining which transactions are valid.

The stable_and_unstable_hashes method returns two vectors of hashes: one for the "stable" portion of the blockchain, which includes all blocks up to and including the most recent common ancestor of all branches, and one for the "unstable" portion of the blockchain, which includes all blocks after the most recent common ancestor. The unstable_hashes method returns only the unstable hashes.

Finally, the height method is used to determine the height of a given branch by recursively following the chain of previous hashes until the genesis block is reached.

Forks

In blockchain technology, a fork is a situation where a blockchain diverges into two or more separate chains, with each chain having its own version of the transaction history. Forks can be intentional or unintentional and can occur due to various reasons like a software update or a disagreement between the network participants.

Filename: tofuri/fork/src/lib.rs

use rocksdb::DBWithThreadMode;
use rocksdb::SingleThreaded;
use std::collections::HashMap;
use std::collections::VecDeque;
use tofuri_address::address;
use tofuri_block::BlockA;
use tofuri_checkpoint::Checkpoint;
use tofuri_core::*;
use tofuri_stake::StakeA;
use tofuri_transaction::TransactionA;
use tofuri_tree::Tree;
use tracing::debug;
use tracing::warn;
#[derive(Debug)]
pub enum Error {
    NotAllowedToForkStableChain,
    Overflow,
}
pub trait Fork {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash>;
    fn get_stakers(&self) -> &VecDeque<AddressBytes>;
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes>;
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_latest_block(&self) -> &BlockA;
    fn get_latest_block_mut(&mut self) -> &mut BlockA;
    fn get_latest_blocks(&self) -> &Vec<BlockA>;
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA>;
    fn is_stable() -> bool;
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool);
}
impl Fork for Stable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        true
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
impl Fork for Unstable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        false
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
#[derive(Default, Debug, Clone)]
pub struct Manager {
    pub stable: Stable,
    pub unstable: Unstable,
}
#[derive(Default, Debug, Clone)]
pub struct Stable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
#[derive(Default, Debug, Clone)]
pub struct Unstable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
impl Manager {
    pub fn unstable(
        &self,
        db: &DBWithThreadMode<SingleThreaded>,
        tree: &Tree,
        trust_fork_after_blocks: usize,
        previous_hash: &Hash,
    ) -> Result<Unstable, Error> {
        if previous_hash == &GENESIS_BLOCK_PREVIOUS_HASH {
            let unstable = Unstable::default();
            return Ok(unstable);
        }
        let first = self.unstable.hashes.first().unwrap();
        let mut hashes = vec![];
        let mut hash = *previous_hash;
        for _ in 0..trust_fork_after_blocks {
            hashes.push(hash);
            if first == &hash {
                break;
            }
            match tree.get(&hash) {
                Some(previous_hash) => hash = *previous_hash,
                None => break,
            };
        }
        if first != &hash && hash != GENESIS_BLOCK_PREVIOUS_HASH {
            return Err(Error::NotAllowedToForkStableChain);
        }
        if let Some(hash) = hashes.last() {
            if hash == &GENESIS_BLOCK_PREVIOUS_HASH {
                hashes.pop();
            }
        }
        hashes.reverse();
        let unstable = Unstable::from(db, &hashes, &self.stable);
        Ok(unstable)
    }
    pub fn update(
        &mut self,
        db: &DBWithThreadMode<SingleThreaded>,
        hashes_1: &[Hash],
        trust_fork_after_blocks: usize,
    ) {
        let hashes_0 = &self.unstable.hashes;
        if hashes_0.len() == trust_fork_after_blocks {
            let block_a = tofuri_db::block::get_a(db, hashes_0.first().unwrap()).unwrap();
            self.stable.append_block(
                &block_a,
                match tofuri_db::block::get_b(db, &block_a.previous_hash) {
                    Ok(block_b) => block_b.timestamp,
                    Err(_) => 0,
                },
            );
        }
        self.unstable = Unstable::from(db, hashes_1, &self.stable);
    }
}
impl Stable {
    pub fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32) {
        append_block(self, block_a, previous_timestamp, false)
    }
    pub fn load(&mut self, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
        load(self, db, hashes)
    }
    pub fn checkpoint(&self) -> Checkpoint {
        Checkpoint {
            height: self.hashes.len(),
            latest_block: self.latest_block.clone(),
            stakers: self.stakers.clone(),
            latest_blocks: self.latest_blocks.clone(),
            map_balance: self.map_balance.clone(),
            map_staked: self.map_staked.clone(),
        }
    }
    pub fn from_checkpoint(hashes: Vec<[u8; 32]>, checkpoint: Checkpoint) -> Stable {
        Stable {
            latest_block: checkpoint.latest_block,
            hashes,
            stakers: checkpoint.stakers,
            latest_blocks: checkpoint.latest_blocks,
            map_balance: checkpoint.map_balance,
            map_staked: checkpoint.map_staked,
        }
    }
}
impl Unstable {
    pub fn from(
        db: &DBWithThreadMode<SingleThreaded>,
        hashes: &[Hash],
        stable: &Stable,
    ) -> Unstable {
        let mut unstable = Unstable {
            hashes: vec![],
            stakers: stable.stakers.clone(),
            map_balance: stable.map_balance.clone(),
            map_staked: stable.map_staked.clone(),
            latest_block: BlockA::default(),
            latest_blocks: stable.latest_blocks.clone(),
        };
        load(&mut unstable, db, hashes);
        unstable
    }
    pub fn check_overflow(
        &self,
        transactions: &Vec<TransactionA>,
        stakes: &Vec<StakeA>,
    ) -> Result<(), Error> {
        let mut map_balance: HashMap<AddressBytes, u128> = HashMap::new();
        let mut map_staked: HashMap<AddressBytes, u128> = HashMap::new();
        for transaction_a in transactions {
            let k = transaction_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            balance = balance
                .checked_sub(transaction_a.amount + transaction_a.fee)
                .ok_or(Error::Overflow)?;
            map_balance.insert(k, balance);
        }
        for stake_a in stakes {
            let k = stake_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            let mut staked = if map_staked.contains_key(&k) {
                *map_staked.get(&k).unwrap()
            } else {
                self.staked(&k)
            };
            if stake_a.deposit {
                balance = balance
                    .checked_sub(stake_a.amount + stake_a.fee)
                    .ok_or(Error::Overflow)?;
            } else {
                balance = balance.checked_sub(stake_a.fee).ok_or(Error::Overflow)?;
                staked = staked.checked_sub(stake_a.amount).ok_or(Error::Overflow)?;
            }
            map_balance.insert(k, balance);
            map_staked.insert(k, staked);
        }
        Ok(())
    }
    pub fn transaction_in_chain(&self, transaction_a: &TransactionA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a
                .transactions
                .iter()
                .any(|a| a.hash == transaction_a.hash)
            {
                return true;
            }
        }
        false
    }
    pub fn stake_in_chain(&self, stake_a: &StakeA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a.stakes.iter().any(|a| a.hash == stake_a.hash) {
                return true;
            }
        }
        false
    }
    pub fn balance(&self, address: &AddressBytes) -> u128 {
        get_balance(self, address)
    }
    pub fn staked(&self, address: &AddressBytes) -> u128 {
        get_staked(self, address)
    }
    pub fn next_staker(&self, timestamp: u32) -> Option<AddressBytes> {
        next_staker(self, timestamp)
    }
    pub fn stakers_offline(&self, timestamp: u32, previous_timestamp: u32) -> Vec<AddressBytes> {
        stakers_offline(self, timestamp, previous_timestamp)
    }
    pub fn stakers_n(&self, n: usize) -> Vec<AddressBytes> {
        stakers_n(self, n).0
    }
}
fn get_balance<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_balance().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn get_staked<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_staked().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn insert_balance<T: Fork>(fork: &mut T, address: AddressBytes, balance: u128) {
    match balance {
        0 => fork.get_map_balance_mut().remove(&address),
        x => fork.get_map_balance_mut().insert(address, x),
    };
}
fn insert_staked<T: Fork>(fork: &mut T, address: AddressBytes, staked: u128) {
    match staked {
        0 => fork.get_map_staked_mut().remove(&address),
        x => fork.get_map_staked_mut().insert(address, x),
    };
}
fn update_stakers<T: Fork>(fork: &mut T, address: AddressBytes) {
    let staked = get_staked(fork, &address);
    let index = fork.get_stakers().iter().position(|x| x == &address);
    let threshold = COIN * (fork.get_stakers().len() + 1) as u128;
    if index.is_none() && staked >= threshold {
        fork.get_stakers_mut().push_back(address);
    } else if index.is_some() && staked < threshold {
        fork.get_stakers_mut().remove(index.unwrap()).unwrap();
    }
}
fn update_0<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    let stakers = stakers_offline(fork, block_a.timestamp, previous_timestamp);
    for (index, staker) in stakers.iter().enumerate() {
        let mut staked = get_staked(fork, staker);
        let penalty = tofuri_util::penalty(index + 1);
        staked = staked.saturating_sub(penalty);
        insert_staked(fork, *staker, staked);
        update_stakers(fork, *staker);
        if !loading && !T::is_stable() {
            warn!(
                amount = tofuri_int::to_string(penalty),
                address = address::encode(staker),
                "Slashed"
            );
        }
    }
    if stakers_n(fork, offline(block_a.timestamp, previous_timestamp)).1 {
        let input_address = block_a.input_address();
        insert_staked(fork, input_address, COIN);
        update_stakers(fork, input_address);
        let address = address::encode(&input_address);
        if !loading && !T::is_stable() {
            warn!(address, "Minted")
        }
        if loading {
            debug!(address, "Minted")
        }
    }
}
fn update_1<T: Fork>(fork: &mut T, block_a: &BlockA) {
    let input_address = block_a.input_address();
    let mut balance = get_balance(fork, &input_address);
    balance += block_a.reward();
    insert_balance(fork, input_address, balance)
}
fn update_2<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for transaction in block_a.transactions.iter() {
        let mut balance_input = get_balance(fork, &transaction.input_address);
        let mut balance_output = get_balance(fork, &transaction.output_address);
        balance_input -= transaction.amount + transaction.fee;
        balance_output += transaction.amount;
        insert_balance(fork, transaction.input_address, balance_input);
        insert_balance(fork, transaction.output_address, balance_output);
    }
    for stake in block_a.stakes.iter() {
        let mut balance = get_balance(fork, &stake.input_address);
        let mut staked = get_staked(fork, &stake.input_address);
        if stake.deposit {
            balance -= stake.amount + stake.fee;
            staked += stake.amount;
        } else {
            balance += stake.amount - stake.fee;
            staked -= stake.amount;
        }
        insert_balance(fork, stake.input_address, balance);
        insert_staked(fork, stake.input_address, staked);
    }
}
fn update_3<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for stake in block_a.stakes.iter() {
        update_stakers(fork, stake.input_address);
    }
}
pub fn update<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    update_0(fork, block_a, previous_timestamp, loading);
    update_1(fork, block_a);
    update_2(fork, block_a);
    update_3(fork, block_a);
}
fn update_latest_blocks<T: Fork>(fork: &mut T, block_a: &BlockA) {
    while fork.get_latest_blocks().first().is_some()
        && tofuri_util::elapsed(
            fork.get_latest_blocks().first().unwrap().timestamp,
            block_a.timestamp,
        )
    {
        (*fork.get_latest_blocks_mut()).remove(0);
    }
    (*fork.get_latest_blocks_mut()).push(block_a.clone());
}
pub fn append_block<T: Fork>(
    fork: &mut T,
    block_a: &BlockA,
    previous_timestamp: u32,
    loading: bool,
) {
    update(fork, block_a, previous_timestamp, loading);
    update_latest_blocks(fork, block_a);
    fork.get_hashes_mut().push(block_a.hash);
    *fork.get_latest_block_mut() = block_a.clone();
}
pub fn load<T: Fork>(fork: &mut T, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
    let mut previous_timestamp = match hashes.first() {
        Some(hash) => tofuri_db::block::get_b(db, hash).unwrap().timestamp,
        None => 0,
    };
    for hash in hashes.iter() {
        let block_a = tofuri_db::block::get_a(db, hash).unwrap();
        fork.append_block(&block_a, previous_timestamp, T::is_stable());
        previous_timestamp = block_a.timestamp;
    }
}
fn stakers_n<T: Fork>(fork: &T, n: usize) -> (Vec<AddressBytes>, bool) {
    fn random_n(slice: &[(AddressBytes, u128)], beta: &Beta, n: u128, modulo: u128) -> usize {
        let random = tofuri_util::random(beta, n, modulo);
        let mut counter = 0;
        for (index, (_, staked)) in slice.iter().enumerate() {
            counter += staked;
            if random <= counter {
                return index;
            }
        }
        unreachable!()
    }
    let mut modulo = 0;
    let mut vec: Vec<(AddressBytes, u128)> = vec![];
    for staker in fork.get_stakers().iter() {
        let staked = get_staked(fork, staker);
        modulo += staked;
        vec.push((*staker, staked));
    }
    vec.sort_by(|a, b| b.1.cmp(&a.1));
    let mut random_queue = vec![];
    for index in 0..(n + 1) {
        let penalty = tofuri_util::penalty(index);
        modulo = modulo.saturating_sub(penalty);
        if modulo == 0 {
            return (random_queue, true);
        }
        let index = random_n(&vec, &fork.get_latest_block().beta, index as u128, modulo);
        vec[index] = (vec[index].0, vec[index].1.saturating_sub(penalty));
        random_queue.push(vec[index].0);
    }
    (random_queue, false)
}
fn offline(timestamp: u32, previous_timestamp: u32) -> usize {
    let diff = timestamp.saturating_sub(previous_timestamp + 1);
    (diff / BLOCK_TIME) as usize
}
pub fn next_staker<T: Fork>(fork: &T, timestamp: u32) -> Option<AddressBytes> {
    match stakers_n(fork, offline(timestamp, fork.get_latest_block().timestamp)) {
        (_, true) => None,
        (x, _) => x.last().copied(),
    }
}
fn stakers_offline<T: Fork>(
    fork: &T,
    timestamp: u32,
    previous_timestamp: u32,
) -> Vec<AddressBytes> {
    match offline(timestamp, previous_timestamp) {
        0 => vec![],
        n => stakers_n(fork, n - 1).0,
    }
}
use rocksdb::DBWithThreadMode;
use rocksdb::SingleThreaded;
use std::collections::HashMap;
use std::collections::VecDeque;
use tofuri_address::address;
use tofuri_block::BlockA;
use tofuri_checkpoint::Checkpoint;
use tofuri_core::*;
use tofuri_stake::StakeA;
use tofuri_transaction::TransactionA;
use tofuri_tree::Tree;
use tracing::debug;
use tracing::warn;
#[derive(Debug)]
pub enum Error {
    NotAllowedToForkStableChain,
    Overflow,
}
pub trait Fork {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash>;
    fn get_stakers(&self) -> &VecDeque<AddressBytes>;
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes>;
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_latest_block(&self) -> &BlockA;
    fn get_latest_block_mut(&mut self) -> &mut BlockA;
    fn get_latest_blocks(&self) -> &Vec<BlockA>;
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA>;
    fn is_stable() -> bool;
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool);
}
impl Fork for Stable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        true
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
impl Fork for Unstable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        false
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
#[derive(Default, Debug, Clone)]
pub struct Manager {
    pub stable: Stable,
    pub unstable: Unstable,
}
#[derive(Default, Debug, Clone)]
pub struct Stable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
#[derive(Default, Debug, Clone)]
pub struct Unstable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
impl Manager {
    pub fn unstable(
        &self,
        db: &DBWithThreadMode<SingleThreaded>,
        tree: &Tree,
        trust_fork_after_blocks: usize,
        previous_hash: &Hash,
    ) -> Result<Unstable, Error> {
        if previous_hash == &GENESIS_BLOCK_PREVIOUS_HASH {
            let unstable = Unstable::default();
            return Ok(unstable);
        }
        let first = self.unstable.hashes.first().unwrap();
        let mut hashes = vec![];
        let mut hash = *previous_hash;
        for _ in 0..trust_fork_after_blocks {
            hashes.push(hash);
            if first == &hash {
                break;
            }
            match tree.get(&hash) {
                Some(previous_hash) => hash = *previous_hash,
                None => break,
            };
        }
        if first != &hash && hash != GENESIS_BLOCK_PREVIOUS_HASH {
            return Err(Error::NotAllowedToForkStableChain);
        }
        if let Some(hash) = hashes.last() {
            if hash == &GENESIS_BLOCK_PREVIOUS_HASH {
                hashes.pop();
            }
        }
        hashes.reverse();
        let unstable = Unstable::from(db, &hashes, &self.stable);
        Ok(unstable)
    }
    pub fn update(
        &mut self,
        db: &DBWithThreadMode<SingleThreaded>,
        hashes_1: &[Hash],
        trust_fork_after_blocks: usize,
    ) {
        let hashes_0 = &self.unstable.hashes;
        if hashes_0.len() == trust_fork_after_blocks {
            let block_a = tofuri_db::block::get_a(db, hashes_0.first().unwrap()).unwrap();
            self.stable.append_block(
                &block_a,
                match tofuri_db::block::get_b(db, &block_a.previous_hash) {
                    Ok(block_b) => block_b.timestamp,
                    Err(_) => 0,
                },
            );
        }
        self.unstable = Unstable::from(db, hashes_1, &self.stable);
    }
}
impl Stable {
    pub fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32) {
        append_block(self, block_a, previous_timestamp, false)
    }
    pub fn load(&mut self, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
        load(self, db, hashes)
    }
    pub fn checkpoint(&self) -> Checkpoint {
        Checkpoint {
            height: self.hashes.len(),
            latest_block: self.latest_block.clone(),
            stakers: self.stakers.clone(),
            latest_blocks: self.latest_blocks.clone(),
            map_balance: self.map_balance.clone(),
            map_staked: self.map_staked.clone(),
        }
    }
    pub fn from_checkpoint(hashes: Vec<[u8; 32]>, checkpoint: Checkpoint) -> Stable {
        Stable {
            latest_block: checkpoint.latest_block,
            hashes,
            stakers: checkpoint.stakers,
            latest_blocks: checkpoint.latest_blocks,
            map_balance: checkpoint.map_balance,
            map_staked: checkpoint.map_staked,
        }
    }
}
impl Unstable {
    pub fn from(
        db: &DBWithThreadMode<SingleThreaded>,
        hashes: &[Hash],
        stable: &Stable,
    ) -> Unstable {
        let mut unstable = Unstable {
            hashes: vec![],
            stakers: stable.stakers.clone(),
            map_balance: stable.map_balance.clone(),
            map_staked: stable.map_staked.clone(),
            latest_block: BlockA::default(),
            latest_blocks: stable.latest_blocks.clone(),
        };
        load(&mut unstable, db, hashes);
        unstable
    }
    pub fn check_overflow(
        &self,
        transactions: &Vec<TransactionA>,
        stakes: &Vec<StakeA>,
    ) -> Result<(), Error> {
        let mut map_balance: HashMap<AddressBytes, u128> = HashMap::new();
        let mut map_staked: HashMap<AddressBytes, u128> = HashMap::new();
        for transaction_a in transactions {
            let k = transaction_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            balance = balance
                .checked_sub(transaction_a.amount + transaction_a.fee)
                .ok_or(Error::Overflow)?;
            map_balance.insert(k, balance);
        }
        for stake_a in stakes {
            let k = stake_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            let mut staked = if map_staked.contains_key(&k) {
                *map_staked.get(&k).unwrap()
            } else {
                self.staked(&k)
            };
            if stake_a.deposit {
                balance = balance
                    .checked_sub(stake_a.amount + stake_a.fee)
                    .ok_or(Error::Overflow)?;
            } else {
                balance = balance.checked_sub(stake_a.fee).ok_or(Error::Overflow)?;
                staked = staked.checked_sub(stake_a.amount).ok_or(Error::Overflow)?;
            }
            map_balance.insert(k, balance);
            map_staked.insert(k, staked);
        }
        Ok(())
    }
    pub fn transaction_in_chain(&self, transaction_a: &TransactionA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a
                .transactions
                .iter()
                .any(|a| a.hash == transaction_a.hash)
            {
                return true;
            }
        }
        false
    }
    pub fn stake_in_chain(&self, stake_a: &StakeA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a.stakes.iter().any(|a| a.hash == stake_a.hash) {
                return true;
            }
        }
        false
    }
    pub fn balance(&self, address: &AddressBytes) -> u128 {
        get_balance(self, address)
    }
    pub fn staked(&self, address: &AddressBytes) -> u128 {
        get_staked(self, address)
    }
    pub fn next_staker(&self, timestamp: u32) -> Option<AddressBytes> {
        next_staker(self, timestamp)
    }
    pub fn stakers_offline(&self, timestamp: u32, previous_timestamp: u32) -> Vec<AddressBytes> {
        stakers_offline(self, timestamp, previous_timestamp)
    }
    pub fn stakers_n(&self, n: usize) -> Vec<AddressBytes> {
        stakers_n(self, n).0
    }
}
fn get_balance<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_balance().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn get_staked<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_staked().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn insert_balance<T: Fork>(fork: &mut T, address: AddressBytes, balance: u128) {
    match balance {
        0 => fork.get_map_balance_mut().remove(&address),
        x => fork.get_map_balance_mut().insert(address, x),
    };
}
fn insert_staked<T: Fork>(fork: &mut T, address: AddressBytes, staked: u128) {
    match staked {
        0 => fork.get_map_staked_mut().remove(&address),
        x => fork.get_map_staked_mut().insert(address, x),
    };
}
fn update_stakers<T: Fork>(fork: &mut T, address: AddressBytes) {
    let staked = get_staked(fork, &address);
    let index = fork.get_stakers().iter().position(|x| x == &address);
    let threshold = COIN * (fork.get_stakers().len() + 1) as u128;
    if index.is_none() && staked >= threshold {
        fork.get_stakers_mut().push_back(address);
    } else if index.is_some() && staked < threshold {
        fork.get_stakers_mut().remove(index.unwrap()).unwrap();
    }
}
fn update_0<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    let stakers = stakers_offline(fork, block_a.timestamp, previous_timestamp);
    for (index, staker) in stakers.iter().enumerate() {
        let mut staked = get_staked(fork, staker);
        let penalty = tofuri_util::penalty(index + 1);
        staked = staked.saturating_sub(penalty);
        insert_staked(fork, *staker, staked);
        update_stakers(fork, *staker);
        if !loading && !T::is_stable() {
            warn!(
                amount = tofuri_int::to_string(penalty),
                address = address::encode(staker),
                "Slashed"
            );
        }
    }
    if stakers_n(fork, offline(block_a.timestamp, previous_timestamp)).1 {
        let input_address = block_a.input_address();
        insert_staked(fork, input_address, COIN);
        update_stakers(fork, input_address);
        let address = address::encode(&input_address);
        if !loading && !T::is_stable() {
            warn!(address, "Minted")
        }
        if loading {
            debug!(address, "Minted")
        }
    }
}
fn update_1<T: Fork>(fork: &mut T, block_a: &BlockA) {
    let input_address = block_a.input_address();
    let mut balance = get_balance(fork, &input_address);
    balance += block_a.reward();
    insert_balance(fork, input_address, balance)
}
fn update_2<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for transaction in block_a.transactions.iter() {
        let mut balance_input = get_balance(fork, &transaction.input_address);
        let mut balance_output = get_balance(fork, &transaction.output_address);
        balance_input -= transaction.amount + transaction.fee;
        balance_output += transaction.amount;
        insert_balance(fork, transaction.input_address, balance_input);
        insert_balance(fork, transaction.output_address, balance_output);
    }
    for stake in block_a.stakes.iter() {
        let mut balance = get_balance(fork, &stake.input_address);
        let mut staked = get_staked(fork, &stake.input_address);
        if stake.deposit {
            balance -= stake.amount + stake.fee;
            staked += stake.amount;
        } else {
            balance += stake.amount - stake.fee;
            staked -= stake.amount;
        }
        insert_balance(fork, stake.input_address, balance);
        insert_staked(fork, stake.input_address, staked);
    }
}
fn update_3<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for stake in block_a.stakes.iter() {
        update_stakers(fork, stake.input_address);
    }
}
pub fn update<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    update_0(fork, block_a, previous_timestamp, loading);
    update_1(fork, block_a);
    update_2(fork, block_a);
    update_3(fork, block_a);
}
fn update_latest_blocks<T: Fork>(fork: &mut T, block_a: &BlockA) {
    while fork.get_latest_blocks().first().is_some()
        && tofuri_util::elapsed(
            fork.get_latest_blocks().first().unwrap().timestamp,
            block_a.timestamp,
        )
    {
        (*fork.get_latest_blocks_mut()).remove(0);
    }
    (*fork.get_latest_blocks_mut()).push(block_a.clone());
}
pub fn append_block<T: Fork>(
    fork: &mut T,
    block_a: &BlockA,
    previous_timestamp: u32,
    loading: bool,
) {
    update(fork, block_a, previous_timestamp, loading);
    update_latest_blocks(fork, block_a);
    fork.get_hashes_mut().push(block_a.hash);
    *fork.get_latest_block_mut() = block_a.clone();
}
pub fn load<T: Fork>(fork: &mut T, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
    let mut previous_timestamp = match hashes.first() {
        Some(hash) => tofuri_db::block::get_b(db, hash).unwrap().timestamp,
        None => 0,
    };
    for hash in hashes.iter() {
        let block_a = tofuri_db::block::get_a(db, hash).unwrap();
        fork.append_block(&block_a, previous_timestamp, T::is_stable());
        previous_timestamp = block_a.timestamp;
    }
}
fn stakers_n<T: Fork>(fork: &T, n: usize) -> (Vec<AddressBytes>, bool) {
    fn random_n(slice: &[(AddressBytes, u128)], beta: &Beta, n: u128, modulo: u128) -> usize {
        let random = tofuri_util::random(beta, n, modulo);
        let mut counter = 0;
        for (index, (_, staked)) in slice.iter().enumerate() {
            counter += staked;
            if random <= counter {
                return index;
            }
        }
        unreachable!()
    }
    let mut modulo = 0;
    let mut vec: Vec<(AddressBytes, u128)> = vec![];
    for staker in fork.get_stakers().iter() {
        let staked = get_staked(fork, staker);
        modulo += staked;
        vec.push((*staker, staked));
    }
    vec.sort_by(|a, b| b.1.cmp(&a.1));
    let mut random_queue = vec![];
    for index in 0..(n + 1) {
        let penalty = tofuri_util::penalty(index);
        modulo = modulo.saturating_sub(penalty);
        if modulo == 0 {
            return (random_queue, true);
        }
        let index = random_n(&vec, &fork.get_latest_block().beta, index as u128, modulo);
        vec[index] = (vec[index].0, vec[index].1.saturating_sub(penalty));
        random_queue.push(vec[index].0);
    }
    (random_queue, false)
}
fn offline(timestamp: u32, previous_timestamp: u32) -> usize {
    let diff = timestamp.saturating_sub(previous_timestamp + 1);
    (diff / BLOCK_TIME) as usize
}
pub fn next_staker<T: Fork>(fork: &T, timestamp: u32) -> Option<AddressBytes> {
    match stakers_n(fork, offline(timestamp, fork.get_latest_block().timestamp)) {
        (_, true) => None,
        (x, _) => x.last().copied(),
    }
}
fn stakers_offline<T: Fork>(
    fork: &T,
    timestamp: u32,
    previous_timestamp: u32,
) -> Vec<AddressBytes> {
    match offline(timestamp, previous_timestamp) {
        0 => vec![],
        n => stakers_n(fork, n - 1).0,
    }
}
use rocksdb::DBWithThreadMode;
use rocksdb::SingleThreaded;
use std::collections::HashMap;
use std::collections::VecDeque;
use tofuri_address::address;
use tofuri_block::BlockA;
use tofuri_checkpoint::Checkpoint;
use tofuri_core::*;
use tofuri_stake::StakeA;
use tofuri_transaction::TransactionA;
use tofuri_tree::Tree;
use tracing::debug;
use tracing::warn;
#[derive(Debug)]
pub enum Error {
    NotAllowedToForkStableChain,
    Overflow,
}
pub trait Fork {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash>;
    fn get_stakers(&self) -> &VecDeque<AddressBytes>;
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes>;
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_latest_block(&self) -> &BlockA;
    fn get_latest_block_mut(&mut self) -> &mut BlockA;
    fn get_latest_blocks(&self) -> &Vec<BlockA>;
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA>;
    fn is_stable() -> bool;
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool);
}
impl Fork for Stable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        true
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
impl Fork for Unstable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        false
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
#[derive(Default, Debug, Clone)]
pub struct Manager {
    pub stable: Stable,
    pub unstable: Unstable,
}
#[derive(Default, Debug, Clone)]
pub struct Stable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
#[derive(Default, Debug, Clone)]
pub struct Unstable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
impl Manager {
    pub fn unstable(
        &self,
        db: &DBWithThreadMode<SingleThreaded>,
        tree: &Tree,
        trust_fork_after_blocks: usize,
        previous_hash: &Hash,
    ) -> Result<Unstable, Error> {
        if previous_hash == &GENESIS_BLOCK_PREVIOUS_HASH {
            let unstable = Unstable::default();
            return Ok(unstable);
        }
        let first = self.unstable.hashes.first().unwrap();
        let mut hashes = vec![];
        let mut hash = *previous_hash;
        for _ in 0..trust_fork_after_blocks {
            hashes.push(hash);
            if first == &hash {
                break;
            }
            match tree.get(&hash) {
                Some(previous_hash) => hash = *previous_hash,
                None => break,
            };
        }
        if first != &hash && hash != GENESIS_BLOCK_PREVIOUS_HASH {
            return Err(Error::NotAllowedToForkStableChain);
        }
        if let Some(hash) = hashes.last() {
            if hash == &GENESIS_BLOCK_PREVIOUS_HASH {
                hashes.pop();
            }
        }
        hashes.reverse();
        let unstable = Unstable::from(db, &hashes, &self.stable);
        Ok(unstable)
    }
    pub fn update(
        &mut self,
        db: &DBWithThreadMode<SingleThreaded>,
        hashes_1: &[Hash],
        trust_fork_after_blocks: usize,
    ) {
        let hashes_0 = &self.unstable.hashes;
        if hashes_0.len() == trust_fork_after_blocks {
            let block_a = tofuri_db::block::get_a(db, hashes_0.first().unwrap()).unwrap();
            self.stable.append_block(
                &block_a,
                match tofuri_db::block::get_b(db, &block_a.previous_hash) {
                    Ok(block_b) => block_b.timestamp,
                    Err(_) => 0,
                },
            );
        }
        self.unstable = Unstable::from(db, hashes_1, &self.stable);
    }
}
impl Stable {
    pub fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32) {
        append_block(self, block_a, previous_timestamp, false)
    }
    pub fn load(&mut self, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
        load(self, db, hashes)
    }
    pub fn checkpoint(&self) -> Checkpoint {
        Checkpoint {
            height: self.hashes.len(),
            latest_block: self.latest_block.clone(),
            stakers: self.stakers.clone(),
            latest_blocks: self.latest_blocks.clone(),
            map_balance: self.map_balance.clone(),
            map_staked: self.map_staked.clone(),
        }
    }
    pub fn from_checkpoint(hashes: Vec<[u8; 32]>, checkpoint: Checkpoint) -> Stable {
        Stable {
            latest_block: checkpoint.latest_block,
            hashes,
            stakers: checkpoint.stakers,
            latest_blocks: checkpoint.latest_blocks,
            map_balance: checkpoint.map_balance,
            map_staked: checkpoint.map_staked,
        }
    }
}
impl Unstable {
    pub fn from(
        db: &DBWithThreadMode<SingleThreaded>,
        hashes: &[Hash],
        stable: &Stable,
    ) -> Unstable {
        let mut unstable = Unstable {
            hashes: vec![],
            stakers: stable.stakers.clone(),
            map_balance: stable.map_balance.clone(),
            map_staked: stable.map_staked.clone(),
            latest_block: BlockA::default(),
            latest_blocks: stable.latest_blocks.clone(),
        };
        load(&mut unstable, db, hashes);
        unstable
    }
    pub fn check_overflow(
        &self,
        transactions: &Vec<TransactionA>,
        stakes: &Vec<StakeA>,
    ) -> Result<(), Error> {
        let mut map_balance: HashMap<AddressBytes, u128> = HashMap::new();
        let mut map_staked: HashMap<AddressBytes, u128> = HashMap::new();
        for transaction_a in transactions {
            let k = transaction_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            balance = balance
                .checked_sub(transaction_a.amount + transaction_a.fee)
                .ok_or(Error::Overflow)?;
            map_balance.insert(k, balance);
        }
        for stake_a in stakes {
            let k = stake_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            let mut staked = if map_staked.contains_key(&k) {
                *map_staked.get(&k).unwrap()
            } else {
                self.staked(&k)
            };
            if stake_a.deposit {
                balance = balance
                    .checked_sub(stake_a.amount + stake_a.fee)
                    .ok_or(Error::Overflow)?;
            } else {
                balance = balance.checked_sub(stake_a.fee).ok_or(Error::Overflow)?;
                staked = staked.checked_sub(stake_a.amount).ok_or(Error::Overflow)?;
            }
            map_balance.insert(k, balance);
            map_staked.insert(k, staked);
        }
        Ok(())
    }
    pub fn transaction_in_chain(&self, transaction_a: &TransactionA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a
                .transactions
                .iter()
                .any(|a| a.hash == transaction_a.hash)
            {
                return true;
            }
        }
        false
    }
    pub fn stake_in_chain(&self, stake_a: &StakeA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a.stakes.iter().any(|a| a.hash == stake_a.hash) {
                return true;
            }
        }
        false
    }
    pub fn balance(&self, address: &AddressBytes) -> u128 {
        get_balance(self, address)
    }
    pub fn staked(&self, address: &AddressBytes) -> u128 {
        get_staked(self, address)
    }
    pub fn next_staker(&self, timestamp: u32) -> Option<AddressBytes> {
        next_staker(self, timestamp)
    }
    pub fn stakers_offline(&self, timestamp: u32, previous_timestamp: u32) -> Vec<AddressBytes> {
        stakers_offline(self, timestamp, previous_timestamp)
    }
    pub fn stakers_n(&self, n: usize) -> Vec<AddressBytes> {
        stakers_n(self, n).0
    }
}
fn get_balance<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_balance().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn get_staked<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_staked().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn insert_balance<T: Fork>(fork: &mut T, address: AddressBytes, balance: u128) {
    match balance {
        0 => fork.get_map_balance_mut().remove(&address),
        x => fork.get_map_balance_mut().insert(address, x),
    };
}
fn insert_staked<T: Fork>(fork: &mut T, address: AddressBytes, staked: u128) {
    match staked {
        0 => fork.get_map_staked_mut().remove(&address),
        x => fork.get_map_staked_mut().insert(address, x),
    };
}
fn update_stakers<T: Fork>(fork: &mut T, address: AddressBytes) {
    let staked = get_staked(fork, &address);
    let index = fork.get_stakers().iter().position(|x| x == &address);
    let threshold = COIN * (fork.get_stakers().len() + 1) as u128;
    if index.is_none() && staked >= threshold {
        fork.get_stakers_mut().push_back(address);
    } else if index.is_some() && staked < threshold {
        fork.get_stakers_mut().remove(index.unwrap()).unwrap();
    }
}
fn update_0<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    let stakers = stakers_offline(fork, block_a.timestamp, previous_timestamp);
    for (index, staker) in stakers.iter().enumerate() {
        let mut staked = get_staked(fork, staker);
        let penalty = tofuri_util::penalty(index + 1);
        staked = staked.saturating_sub(penalty);
        insert_staked(fork, *staker, staked);
        update_stakers(fork, *staker);
        if !loading && !T::is_stable() {
            warn!(
                amount = tofuri_int::to_string(penalty),
                address = address::encode(staker),
                "Slashed"
            );
        }
    }
    if stakers_n(fork, offline(block_a.timestamp, previous_timestamp)).1 {
        let input_address = block_a.input_address();
        insert_staked(fork, input_address, COIN);
        update_stakers(fork, input_address);
        let address = address::encode(&input_address);
        if !loading && !T::is_stable() {
            warn!(address, "Minted")
        }
        if loading {
            debug!(address, "Minted")
        }
    }
}
fn update_1<T: Fork>(fork: &mut T, block_a: &BlockA) {
    let input_address = block_a.input_address();
    let mut balance = get_balance(fork, &input_address);
    balance += block_a.reward();
    insert_balance(fork, input_address, balance)
}
fn update_2<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for transaction in block_a.transactions.iter() {
        let mut balance_input = get_balance(fork, &transaction.input_address);
        let mut balance_output = get_balance(fork, &transaction.output_address);
        balance_input -= transaction.amount + transaction.fee;
        balance_output += transaction.amount;
        insert_balance(fork, transaction.input_address, balance_input);
        insert_balance(fork, transaction.output_address, balance_output);
    }
    for stake in block_a.stakes.iter() {
        let mut balance = get_balance(fork, &stake.input_address);
        let mut staked = get_staked(fork, &stake.input_address);
        if stake.deposit {
            balance -= stake.amount + stake.fee;
            staked += stake.amount;
        } else {
            balance += stake.amount - stake.fee;
            staked -= stake.amount;
        }
        insert_balance(fork, stake.input_address, balance);
        insert_staked(fork, stake.input_address, staked);
    }
}
fn update_3<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for stake in block_a.stakes.iter() {
        update_stakers(fork, stake.input_address);
    }
}
pub fn update<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    update_0(fork, block_a, previous_timestamp, loading);
    update_1(fork, block_a);
    update_2(fork, block_a);
    update_3(fork, block_a);
}
fn update_latest_blocks<T: Fork>(fork: &mut T, block_a: &BlockA) {
    while fork.get_latest_blocks().first().is_some()
        && tofuri_util::elapsed(
            fork.get_latest_blocks().first().unwrap().timestamp,
            block_a.timestamp,
        )
    {
        (*fork.get_latest_blocks_mut()).remove(0);
    }
    (*fork.get_latest_blocks_mut()).push(block_a.clone());
}
pub fn append_block<T: Fork>(
    fork: &mut T,
    block_a: &BlockA,
    previous_timestamp: u32,
    loading: bool,
) {
    update(fork, block_a, previous_timestamp, loading);
    update_latest_blocks(fork, block_a);
    fork.get_hashes_mut().push(block_a.hash);
    *fork.get_latest_block_mut() = block_a.clone();
}
pub fn load<T: Fork>(fork: &mut T, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
    let mut previous_timestamp = match hashes.first() {
        Some(hash) => tofuri_db::block::get_b(db, hash).unwrap().timestamp,
        None => 0,
    };
    for hash in hashes.iter() {
        let block_a = tofuri_db::block::get_a(db, hash).unwrap();
        fork.append_block(&block_a, previous_timestamp, T::is_stable());
        previous_timestamp = block_a.timestamp;
    }
}
fn stakers_n<T: Fork>(fork: &T, n: usize) -> (Vec<AddressBytes>, bool) {
    fn random_n(slice: &[(AddressBytes, u128)], beta: &Beta, n: u128, modulo: u128) -> usize {
        let random = tofuri_util::random(beta, n, modulo);
        let mut counter = 0;
        for (index, (_, staked)) in slice.iter().enumerate() {
            counter += staked;
            if random <= counter {
                return index;
            }
        }
        unreachable!()
    }
    let mut modulo = 0;
    let mut vec: Vec<(AddressBytes, u128)> = vec![];
    for staker in fork.get_stakers().iter() {
        let staked = get_staked(fork, staker);
        modulo += staked;
        vec.push((*staker, staked));
    }
    vec.sort_by(|a, b| b.1.cmp(&a.1));
    let mut random_queue = vec![];
    for index in 0..(n + 1) {
        let penalty = tofuri_util::penalty(index);
        modulo = modulo.saturating_sub(penalty);
        if modulo == 0 {
            return (random_queue, true);
        }
        let index = random_n(&vec, &fork.get_latest_block().beta, index as u128, modulo);
        vec[index] = (vec[index].0, vec[index].1.saturating_sub(penalty));
        random_queue.push(vec[index].0);
    }
    (random_queue, false)
}
fn offline(timestamp: u32, previous_timestamp: u32) -> usize {
    let diff = timestamp.saturating_sub(previous_timestamp + 1);
    (diff / BLOCK_TIME) as usize
}
pub fn next_staker<T: Fork>(fork: &T, timestamp: u32) -> Option<AddressBytes> {
    match stakers_n(fork, offline(timestamp, fork.get_latest_block().timestamp)) {
        (_, true) => None,
        (x, _) => x.last().copied(),
    }
}
fn stakers_offline<T: Fork>(
    fork: &T,
    timestamp: u32,
    previous_timestamp: u32,
) -> Vec<AddressBytes> {
    match offline(timestamp, previous_timestamp) {
        0 => vec![],
        n => stakers_n(fork, n - 1).0,
    }
}
use rocksdb::DBWithThreadMode;
use rocksdb::SingleThreaded;
use std::collections::HashMap;
use std::collections::VecDeque;
use tofuri_address::address;
use tofuri_block::BlockA;
use tofuri_checkpoint::Checkpoint;
use tofuri_core::*;
use tofuri_stake::StakeA;
use tofuri_transaction::TransactionA;
use tofuri_tree::Tree;
use tracing::debug;
use tracing::warn;
#[derive(Debug)]
pub enum Error {
    NotAllowedToForkStableChain,
    Overflow,
}
pub trait Fork {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash>;
    fn get_stakers(&self) -> &VecDeque<AddressBytes>;
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes>;
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128>;
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128>;
    fn get_latest_block(&self) -> &BlockA;
    fn get_latest_block_mut(&mut self) -> &mut BlockA;
    fn get_latest_blocks(&self) -> &Vec<BlockA>;
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA>;
    fn is_stable() -> bool;
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool);
}
impl Fork for Stable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        true
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
impl Fork for Unstable {
    fn get_hashes_mut(&mut self) -> &mut Vec<Hash> {
        &mut self.hashes
    }
    fn get_stakers(&self) -> &VecDeque<AddressBytes> {
        &self.stakers
    }
    fn get_stakers_mut(&mut self) -> &mut VecDeque<AddressBytes> {
        &mut self.stakers
    }
    fn get_map_balance(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_balance
    }
    fn get_map_balance_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_balance
    }
    fn get_map_staked(&self) -> &HashMap<AddressBytes, u128> {
        &self.map_staked
    }
    fn get_map_staked_mut(&mut self) -> &mut HashMap<AddressBytes, u128> {
        &mut self.map_staked
    }
    fn get_latest_block(&self) -> &BlockA {
        &self.latest_block
    }
    fn get_latest_block_mut(&mut self) -> &mut BlockA {
        &mut self.latest_block
    }
    fn get_latest_blocks(&self) -> &Vec<BlockA> {
        &self.latest_blocks
    }
    fn get_latest_blocks_mut(&mut self) -> &mut Vec<BlockA> {
        &mut self.latest_blocks
    }
    fn is_stable() -> bool {
        false
    }
    fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
        append_block(self, block_a, previous_timestamp, loading)
    }
}
#[derive(Default, Debug, Clone)]
pub struct Manager {
    pub stable: Stable,
    pub unstable: Unstable,
}
#[derive(Default, Debug, Clone)]
pub struct Stable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
#[derive(Default, Debug, Clone)]
pub struct Unstable {
    pub latest_block: BlockA,
    pub hashes: Vec<Hash>,
    pub stakers: VecDeque<AddressBytes>,
    latest_blocks: Vec<BlockA>,
    map_balance: HashMap<AddressBytes, u128>,
    map_staked: HashMap<AddressBytes, u128>,
}
impl Manager {
    pub fn unstable(
        &self,
        db: &DBWithThreadMode<SingleThreaded>,
        tree: &Tree,
        trust_fork_after_blocks: usize,
        previous_hash: &Hash,
    ) -> Result<Unstable, Error> {
        if previous_hash == &GENESIS_BLOCK_PREVIOUS_HASH {
            let unstable = Unstable::default();
            return Ok(unstable);
        }
        let first = self.unstable.hashes.first().unwrap();
        let mut hashes = vec![];
        let mut hash = *previous_hash;
        for _ in 0..trust_fork_after_blocks {
            hashes.push(hash);
            if first == &hash {
                break;
            }
            match tree.get(&hash) {
                Some(previous_hash) => hash = *previous_hash,
                None => break,
            };
        }
        if first != &hash && hash != GENESIS_BLOCK_PREVIOUS_HASH {
            return Err(Error::NotAllowedToForkStableChain);
        }
        if let Some(hash) = hashes.last() {
            if hash == &GENESIS_BLOCK_PREVIOUS_HASH {
                hashes.pop();
            }
        }
        hashes.reverse();
        let unstable = Unstable::from(db, &hashes, &self.stable);
        Ok(unstable)
    }
    pub fn update(
        &mut self,
        db: &DBWithThreadMode<SingleThreaded>,
        hashes_1: &[Hash],
        trust_fork_after_blocks: usize,
    ) {
        let hashes_0 = &self.unstable.hashes;
        if hashes_0.len() == trust_fork_after_blocks {
            let block_a = tofuri_db::block::get_a(db, hashes_0.first().unwrap()).unwrap();
            self.stable.append_block(
                &block_a,
                match tofuri_db::block::get_b(db, &block_a.previous_hash) {
                    Ok(block_b) => block_b.timestamp,
                    Err(_) => 0,
                },
            );
        }
        self.unstable = Unstable::from(db, hashes_1, &self.stable);
    }
}
impl Stable {
    pub fn append_block(&mut self, block_a: &BlockA, previous_timestamp: u32) {
        append_block(self, block_a, previous_timestamp, false)
    }
    pub fn load(&mut self, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
        load(self, db, hashes)
    }
    pub fn checkpoint(&self) -> Checkpoint {
        Checkpoint {
            height: self.hashes.len(),
            latest_block: self.latest_block.clone(),
            stakers: self.stakers.clone(),
            latest_blocks: self.latest_blocks.clone(),
            map_balance: self.map_balance.clone(),
            map_staked: self.map_staked.clone(),
        }
    }
    pub fn from_checkpoint(hashes: Vec<[u8; 32]>, checkpoint: Checkpoint) -> Stable {
        Stable {
            latest_block: checkpoint.latest_block,
            hashes,
            stakers: checkpoint.stakers,
            latest_blocks: checkpoint.latest_blocks,
            map_balance: checkpoint.map_balance,
            map_staked: checkpoint.map_staked,
        }
    }
}
impl Unstable {
    pub fn from(
        db: &DBWithThreadMode<SingleThreaded>,
        hashes: &[Hash],
        stable: &Stable,
    ) -> Unstable {
        let mut unstable = Unstable {
            hashes: vec![],
            stakers: stable.stakers.clone(),
            map_balance: stable.map_balance.clone(),
            map_staked: stable.map_staked.clone(),
            latest_block: BlockA::default(),
            latest_blocks: stable.latest_blocks.clone(),
        };
        load(&mut unstable, db, hashes);
        unstable
    }
    pub fn check_overflow(
        &self,
        transactions: &Vec<TransactionA>,
        stakes: &Vec<StakeA>,
    ) -> Result<(), Error> {
        let mut map_balance: HashMap<AddressBytes, u128> = HashMap::new();
        let mut map_staked: HashMap<AddressBytes, u128> = HashMap::new();
        for transaction_a in transactions {
            let k = transaction_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            balance = balance
                .checked_sub(transaction_a.amount + transaction_a.fee)
                .ok_or(Error::Overflow)?;
            map_balance.insert(k, balance);
        }
        for stake_a in stakes {
            let k = stake_a.input_address;
            let mut balance = if map_balance.contains_key(&k) {
                *map_balance.get(&k).unwrap()
            } else {
                self.balance(&k)
            };
            let mut staked = if map_staked.contains_key(&k) {
                *map_staked.get(&k).unwrap()
            } else {
                self.staked(&k)
            };
            if stake_a.deposit {
                balance = balance
                    .checked_sub(stake_a.amount + stake_a.fee)
                    .ok_or(Error::Overflow)?;
            } else {
                balance = balance.checked_sub(stake_a.fee).ok_or(Error::Overflow)?;
                staked = staked.checked_sub(stake_a.amount).ok_or(Error::Overflow)?;
            }
            map_balance.insert(k, balance);
            map_staked.insert(k, staked);
        }
        Ok(())
    }
    pub fn transaction_in_chain(&self, transaction_a: &TransactionA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a
                .transactions
                .iter()
                .any(|a| a.hash == transaction_a.hash)
            {
                return true;
            }
        }
        false
    }
    pub fn stake_in_chain(&self, stake_a: &StakeA) -> bool {
        for block_a in self.latest_blocks.iter() {
            if block_a.stakes.iter().any(|a| a.hash == stake_a.hash) {
                return true;
            }
        }
        false
    }
    pub fn balance(&self, address: &AddressBytes) -> u128 {
        get_balance(self, address)
    }
    pub fn staked(&self, address: &AddressBytes) -> u128 {
        get_staked(self, address)
    }
    pub fn next_staker(&self, timestamp: u32) -> Option<AddressBytes> {
        next_staker(self, timestamp)
    }
    pub fn stakers_offline(&self, timestamp: u32, previous_timestamp: u32) -> Vec<AddressBytes> {
        stakers_offline(self, timestamp, previous_timestamp)
    }
    pub fn stakers_n(&self, n: usize) -> Vec<AddressBytes> {
        stakers_n(self, n).0
    }
}
fn get_balance<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_balance().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn get_staked<T: Fork>(fork: &T, address: &AddressBytes) -> u128 {
    match fork.get_map_staked().get(address) {
        Some(b) => *b,
        None => 0,
    }
}
fn insert_balance<T: Fork>(fork: &mut T, address: AddressBytes, balance: u128) {
    match balance {
        0 => fork.get_map_balance_mut().remove(&address),
        x => fork.get_map_balance_mut().insert(address, x),
    };
}
fn insert_staked<T: Fork>(fork: &mut T, address: AddressBytes, staked: u128) {
    match staked {
        0 => fork.get_map_staked_mut().remove(&address),
        x => fork.get_map_staked_mut().insert(address, x),
    };
}
fn update_stakers<T: Fork>(fork: &mut T, address: AddressBytes) {
    let staked = get_staked(fork, &address);
    let index = fork.get_stakers().iter().position(|x| x == &address);
    let threshold = COIN * (fork.get_stakers().len() + 1) as u128;
    if index.is_none() && staked >= threshold {
        fork.get_stakers_mut().push_back(address);
    } else if index.is_some() && staked < threshold {
        fork.get_stakers_mut().remove(index.unwrap()).unwrap();
    }
}
fn update_0<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    let stakers = stakers_offline(fork, block_a.timestamp, previous_timestamp);
    for (index, staker) in stakers.iter().enumerate() {
        let mut staked = get_staked(fork, staker);
        let penalty = tofuri_util::penalty(index + 1);
        staked = staked.saturating_sub(penalty);
        insert_staked(fork, *staker, staked);
        update_stakers(fork, *staker);
        if !loading && !T::is_stable() {
            warn!(
                amount = tofuri_int::to_string(penalty),
                address = address::encode(staker),
                "Slashed"
            );
        }
    }
    if stakers_n(fork, offline(block_a.timestamp, previous_timestamp)).1 {
        let input_address = block_a.input_address();
        insert_staked(fork, input_address, COIN);
        update_stakers(fork, input_address);
        let address = address::encode(&input_address);
        if !loading && !T::is_stable() {
            warn!(address, "Minted")
        }
        if loading {
            debug!(address, "Minted")
        }
    }
}
fn update_1<T: Fork>(fork: &mut T, block_a: &BlockA) {
    let input_address = block_a.input_address();
    let mut balance = get_balance(fork, &input_address);
    balance += block_a.reward();
    insert_balance(fork, input_address, balance)
}
fn update_2<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for transaction in block_a.transactions.iter() {
        let mut balance_input = get_balance(fork, &transaction.input_address);
        let mut balance_output = get_balance(fork, &transaction.output_address);
        balance_input -= transaction.amount + transaction.fee;
        balance_output += transaction.amount;
        insert_balance(fork, transaction.input_address, balance_input);
        insert_balance(fork, transaction.output_address, balance_output);
    }
    for stake in block_a.stakes.iter() {
        let mut balance = get_balance(fork, &stake.input_address);
        let mut staked = get_staked(fork, &stake.input_address);
        if stake.deposit {
            balance -= stake.amount + stake.fee;
            staked += stake.amount;
        } else {
            balance += stake.amount - stake.fee;
            staked -= stake.amount;
        }
        insert_balance(fork, stake.input_address, balance);
        insert_staked(fork, stake.input_address, staked);
    }
}
fn update_3<T: Fork>(fork: &mut T, block_a: &BlockA) {
    for stake in block_a.stakes.iter() {
        update_stakers(fork, stake.input_address);
    }
}
pub fn update<T: Fork>(fork: &mut T, block_a: &BlockA, previous_timestamp: u32, loading: bool) {
    update_0(fork, block_a, previous_timestamp, loading);
    update_1(fork, block_a);
    update_2(fork, block_a);
    update_3(fork, block_a);
}
fn update_latest_blocks<T: Fork>(fork: &mut T, block_a: &BlockA) {
    while fork.get_latest_blocks().first().is_some()
        && tofuri_util::elapsed(
            fork.get_latest_blocks().first().unwrap().timestamp,
            block_a.timestamp,
        )
    {
        (*fork.get_latest_blocks_mut()).remove(0);
    }
    (*fork.get_latest_blocks_mut()).push(block_a.clone());
}
pub fn append_block<T: Fork>(
    fork: &mut T,
    block_a: &BlockA,
    previous_timestamp: u32,
    loading: bool,
) {
    update(fork, block_a, previous_timestamp, loading);
    update_latest_blocks(fork, block_a);
    fork.get_hashes_mut().push(block_a.hash);
    *fork.get_latest_block_mut() = block_a.clone();
}
pub fn load<T: Fork>(fork: &mut T, db: &DBWithThreadMode<SingleThreaded>, hashes: &[Hash]) {
    let mut previous_timestamp = match hashes.first() {
        Some(hash) => tofuri_db::block::get_b(db, hash).unwrap().timestamp,
        None => 0,
    };
    for hash in hashes.iter() {
        let block_a = tofuri_db::block::get_a(db, hash).unwrap();
        fork.append_block(&block_a, previous_timestamp, T::is_stable());
        previous_timestamp = block_a.timestamp;
    }
}
fn stakers_n<T: Fork>(fork: &T, n: usize) -> (Vec<AddressBytes>, bool) {
    fn random_n(slice: &[(AddressBytes, u128)], beta: &Beta, n: u128, modulo: u128) -> usize {
        let random = tofuri_util::random(beta, n, modulo);
        let mut counter = 0;
        for (index, (_, staked)) in slice.iter().enumerate() {
            counter += staked;
            if random <= counter {
                return index;
            }
        }
        unreachable!()
    }
    let mut modulo = 0;
    let mut vec: Vec<(AddressBytes, u128)> = vec![];
    for staker in fork.get_stakers().iter() {
        let staked = get_staked(fork, staker);
        modulo += staked;
        vec.push((*staker, staked));
    }
    vec.sort_by(|a, b| b.1.cmp(&a.1));
    let mut random_queue = vec![];
    for index in 0..(n + 1) {
        let penalty = tofuri_util::penalty(index);
        modulo = modulo.saturating_sub(penalty);
        if modulo == 0 {
            return (random_queue, true);
        }
        let index = random_n(&vec, &fork.get_latest_block().beta, index as u128, modulo);
        vec[index] = (vec[index].0, vec[index].1.saturating_sub(penalty));
        random_queue.push(vec[index].0);
    }
    (random_queue, false)
}
fn offline(timestamp: u32, previous_timestamp: u32) -> usize {
    let diff = timestamp.saturating_sub(previous_timestamp + 1);
    (diff / BLOCK_TIME) as usize
}
pub fn next_staker<T: Fork>(fork: &T, timestamp: u32) -> Option<AddressBytes> {
    match stakers_n(fork, offline(timestamp, fork.get_latest_block().timestamp)) {
        (_, true) => None,
        (x, _) => x.last().copied(),
    }
}
fn stakers_offline<T: Fork>(
    fork: &T,
    timestamp: u32,
    previous_timestamp: u32,
) -> Vec<AddressBytes> {
    match offline(timestamp, previous_timestamp) {
        0 => vec![],
        n => stakers_n(fork, n - 1).0,
    }
}

The given code is an implementation of Forks in Rust programming language. The code defines two traits - Fork and Manager. The Fork trait defines a set of methods that can be implemented by both Stable and Unstable structs. The Manager struct contains instances of both Stable and Unstable structs and can be used to manage forks.

The Stable struct represents the stable chain, which is the chain with the longest history and is considered to be the correct chain. The Unstable struct represents an unstable chain that is diverging from the stable chain. Both Stable and Unstable structs implement the Fork trait and contain information like the latest block, stakers, balances, and staked amounts.

The append_block method in the Fork trait is used to append a new block to the chain. It takes a reference to the BlockA struct, previous timestamp, and a loading flag as input. The Manager struct can be used to manage forks and switch between the stable and unstable chains.

RPC

API

The Tofuri API is a web-based interface for interacting with the Tofuri cryptocurrency blockchain. It provides a range of endpoints for retrieving information about the blockchain, including current balances, staking information, block heights and hashes, and more. Additionally, the API supports the submission of transactions and stakes.

Synchronization

Time

In any blockchain-based cryptocurrency, time synchronization is crucial because it enables all nodes in the network to agree on the order and validity of transactions and blocks. This is particularly important in Tofuri cryptocurrency, as it is designed to use a proof-of-work consensus algorithm, where nodes compete to add new blocks to the blockchain and earn rewards.

If nodes in the Tofuri network have different times, they may disagree on which blocks are valid or which transactions occurred first. For example, if two nodes receive conflicting blocks at the same height but with different timestamps, they cannot determine which block is the correct one without synchronized time.

Time synchronization ensures that all nodes have an accurate and consistent understanding of the blockchain's state, which is essential for achieving consensus on the network. Without it, nodes may inadvertently mine invalid blocks, leading to forks in the blockchain, or fail to recognize legitimate transactions, resulting in potential double-spending attacks.

Therefore, Tofuri cryptocurrency requires time synchronization to ensure the integrity and security of its blockchain. By using a protocol such as the Network Time Protocol (NTP) to synchronize clocks across the network, Tofuri nodes can agree on the order and validity of transactions and blocks, ultimately strengthening the network's overall trust and reliability.

Developers

Tofuri is an open-source proof-of-stake cryptocurrency written entirely in Rust, and is designed to be fast, secure, and scalable. If you are a developer who is interested in contributing to Tofuri, there are several ways you can get involved:

Code contributions

As Tofuri is written entirely in Rust, if you have experience in Rust development, you can contribute by writing code. You can start by checking out the Tofuri GitHub repository and reading through the code to get an understanding of how the project is structured. Then, you can pick an issue to work on or propose a new feature that you think would be useful to the project. Make sure to follow the project's contribution guidelines and submit your code as a pull request.

Testing

Testing is an essential part of software development, and Tofuri needs robust testing to ensure that it is stable and reliable. If you have experience in testing, you can contribute to Tofuri by writing tests and ensuring that the project passes all tests before releasing new versions.

Bug reporting

Even the best software has bugs, and Tofuri is no exception. If you encounter a bug while using Tofuri, you can contribute by reporting the bug on the project's GitHub issue tracker. Be sure to provide as much information as possible, including steps to reproduce the bug and any error messages that you received.

Documentation

Good documentation is essential for any software project, and Tofuri is no exception. If you have strong writing skills, you can contribute to Tofuri by helping to improve the project's documentation. This could involve writing tutorials, updating the API documentation, or creating examples to help users understand how to use the project.

Community building

Building a strong community is essential for any open-source project, and Tofuri is no exception. If you have experience in community building or social media management, you can contribute by helping to promote the project on social media or by participating in community events and meetups.

Summary

Overall, there are many ways to contribute to the Tofuri project, and developers of all skill levels and backgrounds are welcome. Whether you're a seasoned Rust developer or just starting out, there's a place for you in the Tofuri community. By contributing to Tofuri, you can help make the project more secure, reliable, and useful for users around the world.

Automating payments