# Develop a simple blockchain with rust

By [skka3134](https://paragraph.com/@skka3134) · 2023-07-27

---

The simple structure of a blockchain can be simply understood as countless such blocks connected like a chain to form a blockchain.

![](https://storage.googleapis.com/papyrus_images/bf8dd989348aade796516982700012d02c13f6561f777f06bb3d941461901aa3.png)

The green part is called the block header, including (pre hash, tx hash, time)

The black part and the blue part are called the block body, including (hash, transaction)

Where pre hash is the hash of the previous block

time represents the transaction time, timestamp

The tx hash is used to ensure that the data is not tampered with. The data of each block can theoretically be tampered with, but the hash will not match after the modification.

transaction is transaction information

Finally, there is the hash value of the entire block, which is equivalent to the identification of each block. Similarly, as long as one piece of data in the block is changed, the hash value will change.

On the code! ! !

1.First we need to use the package, open the terminal

    cargo add serde 
    cargo add bincode
    cargo add rust-crypto
    cargo add chrono
    

2.The package serde is used for serialization and deserialization. Serialization and deserialization are very common functions, which are extremely common in network transmission and data storage. The general explanation of serialization and deserialization is: seriallization serialization: convert the object into a format that is convenient for transmission, common serialization formats: binary format, byte array, json string, xml string. deseriallization deserialization: the process of restoring serialized data into objects.

The package bincode is a binary encoding format.

The package crypto is for hash

The package chrono is for timestamp

3.Add the following code at the top

    use bincode;
    use serde::{Deserialize, Serialize};
    use crypto::digest::Digest;
    use crypto::sha3::Sha3;
    use chrono::prelude::*;
    

4.Define the block header

     struct BlockHeader {
         time: i64,
         tx_hash: String,
         pre_hash: String,
    }
    

5.Define blocks

     struct Block {
         header: BlockHeader,
         hash: String,
         data: String, //transactions data
    }
    

6.Use the package just added to write two methods for serialization and deserialization.

    //Serializatize
    fn my_serialize<T: ?Sized>(value: &T) -> Vec<u8> 
        where T: Serialize,
    {
        let seialized = bincode::serialize(value).unwrap();
        seialized
    }
    //deserialize
    fn my_deserialize<'a, T>(bytes: &'a[u8]) -> T 
        where T: Deserialize<'a>,
    {
        let deserialized = bincode::deserialize(bytes).unwrap();
        deserialized
    }
    

7.Use the package rust-crypto to find the hash

    fn get_hash(value: &[u8]) -> String {
        let mut hasher = Sha3::sha3_256();
        hasher.input(value);
        hasher.result_str()
    }
    

8.Implement these methods for the previously defined Block

    impl Block {
        fn set_hash(&mut self) {
            let header = coder::my_serialize(&(self.header));
            self.hash = coder::get_hash(&header[..]);
        }
    
         fn new_block(data: String, pre_hash: String) -> Block {
            let transactions = coder::my_serialize(&data);
            let tx_hash = coder::get_hash(&transactions[..]);
    
            let time = Utc::now().timestamp();
    
            let mut block = Block {
                header: BlockHeader {
                    time: time,
                    tx_hash: tx_hash,  //transactions data merkle root hash
                    pre_hash: pre_hash,
                },
                hash: "".to_string(),
                data: data,
            };
    
            block.set_hash();
            block
        }
    }
    

9.Define blockchain

    struct BlockChain {
        blocks: Vec<block::Block>,
    }
    impl BlockChain {
       fn add_block(&mut self, data: String) {
            let pre_block = &self.blocks[self.blocks.len() - 1];
            let new_block = block::Block::new_block(data, pre_block.hash.clone());
            self.blocks.push(new_block);
        }
    
        fn new_genesis_block() -> block::Block {
            block::Block::new_block("This is genesis block".to_string(), String::from(""))
        }
    
         fn new_blockchain() -> BlockChain {
            BlockChain {
                blocks: vec![BlockChain::new_genesis_block()],
            }
        }
    }
    

10.Define the main method

    fn main() {
        let mut bc = blockchain::BlockChain::new_blockchain();
        bc.add_block(String::from("a -> b: 5 btc"));
        bc.add_block("c -> d: 1 btc".to_string());
        for b in bc.blocks {
            println!("++++++++++++++++++++++++++++++++++++++++++++");
            println!("{:#?}", b);
            println!("");
        }
    }
    

The final code should look like this.

    use bincode;
    use serde::{Deserialize, Serialize};
    use crypto::digest::Digest;
    use crypto::sha3::Sha3;
    use chrono::prelude::*;
    
    
     struct BlockHeader {
         time: i64,
         tx_hash: String,
         pre_hash: String,
    }
    
     struct Block {
         header: BlockHeader,
         hash: String,
         data: String, //transactions data
    }
    impl Block {
        fn set_hash(&mut self) {
            let header = coder::my_serialize(&(self.header));
            self.hash = coder::get_hash(&header[..]);
        }
    
         fn new_block(data: String, pre_hash: String) -> Block {
            let transactions = coder::my_serialize(&data);
            let tx_hash = coder::get_hash(&transactions[..]);
    
            let time = Utc::now().timestamp();
    
            let mut block = Block {
                header: BlockHeader {
                    time: time,
                    tx_hash: tx_hash,  //transactions data merkle root hash
                    pre_hash: pre_hash,
                },
                hash: "".to_string(),
                data: data,
            };
    
            block.set_hash();
            block
        }
    }
    
    
    fn my_serialize<T: ?Sized>(value: &T) -> Vec<u8> 
        where T: Serialize,
    {
        let seialized = bincode::serialize(value).unwrap();
        seialized
    }
    
    fn my_deserialize<'a, T>(bytes: &'a[u8]) -> T 
        where T: Deserialize<'a>,
    {
        let deserialized = bincode::deserialize(bytes).unwrap();
        deserialized
    }
    
    fn get_hash(value: &[u8]) -> String {
        let mut hasher = Sha3::sha3_256();
        hasher.input(value);
        hasher.result_str()
    }
    
    
    
    
    struct BlockChain {
        blocks: Vec<block::Block>,
    }
    
    impl BlockChain {
        fn add_block(&mut self, data: String) {
            let pre_block = &self.blocks[self.blocks.len() - 1];
            let new_block = block::Block::new_block(data, pre_block.hash.clone());
            self.blocks.push(new_block);
        }
    
        fn new_genesis_block() -> block::Block {
            block::Block::new_block("This is genesis block".to_string(), String::from(""))
        }
    
         fn new_blockchain() -> BlockChain {
            BlockChain {
                blocks: vec![BlockChain::new_genesis_block()],
            }
        }
    }
    

Cargo run, the effect

![](https://storage.googleapis.com/papyrus_images/0996675eb43cab18920678ab57b19ed1be5219bd0e557bf356404c702fb7ae22.png)

If you want to simulate mining, use sleep for about 10s

---

*Originally published on [skka3134](https://paragraph.com/@skka3134/develop-a-simple-blockchain-with-rust)*
