Rust实现简单的区块链结构

新建一个cargo项目,增加一个Cargo.toml用来配置整个Rust项目,配置如下。

[workspace]
members=[
"main",
"core",
"utils",
]

在整个项目中有三部分,其中core模块和utils模块都是lib,使用cargo new core --lib创建,main部分是测试和创建区块链的相关代码。

首先需要编写core模块,在这个模块中主要编写区块的结点数据结构和区块链数据结构,在结点数据结构中包含一个结点的头数据结构,创建一个block.rs文件,用来编写结点的数据结构。

use chrono::prelude::Local;
use utils::coder;
use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct BlockHeader {
    pub time: i64,
    // transactionns data merkle root hash
    pub tx_hash: String,
    pub pre_hash: String,
}
#[derive(Serialize, Deserialize, Debug, PartialEq, Eq)]
pub struct Block {
    pub header:BlockHeader,
    pub hash:String,
    // transactions data
    pub data:String,
 }
 impl Block {
     fn set_hash(&mut self){
         self.header.time =Local::now().timestamp();
         let header =coder::my_serialize(&self.header);
         self.hash= coder::get_hash(&header[..]);
     }

     pub fn new_block(data:String,pre_hash:String)->Block{
         let transactions=coder::my_serialize(&data);
         let tx_hash=coder::get_hash(&transactions[..]);

         let time =Local::now().timestamp();

         let mut block=Block{
             header:BlockHeader{
                    time: time,
                    tx_hash:tx_hash,
                    pre_hash:pre_hash,
                },
                hash:"".to_string(),
                data:data,
         };
        block.set_hash();
        block
     }
 }

在编写数据结构时需要让此结构支持序列化和反序列化,(打印、相等对比不是必要的),需要引入serde模块,需要使用时间戳,所以引入chrono模块,修改Cargo.toml文件,序列化和反序列化以及Hash方法都编写在Utils模块中,所以需要引入自己编写的utils模块,如下所示。

[package]
name = "core"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
chrono = "0.4"
serde = {version="1.0.136", features=["derive"]}
utils = {path = "../utils"}

在区块链数据结构中应当包含区块结点结构,编写一个blockchain.rs文件,以Vector的方式存储这些结点,如下代码所示

use crate::block;
pub struct BlockChain {
    pub blocks: Vec<block::Block>,
}

impl BlockChain {
    pub 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);
    }
    // 创世区块
    pub fn new_genesis_block()->block::Block{
        block::Block::new_block("This is genesis block".to_string(),String::from(""))
    }
    pub fn new_blockchain()->BlockChain{
        BlockChain{
            blocks:vec![BlockChain::new_genesis_block()]
        }
    }
}

在core模块中应当暴露出block和blockchain,所以修改lib.rs,如下代码所示。

pub mod block;
pub mod blockchain;

然后编写utils模块,在这个文件中应当提供数据序列化和反序列化的方法,如下代码所示。

// 序列化和反序列化
// 使用第三方crates.io
use bincode;
use serde::{Deserialize, Serialize};
use crypto::digest::Digest;
use crypto::sha3::Sha3;
/**
 * 序列化
 * 编译时大小不确定,使用范型
 * 编译时需要限制范型本身是可以被序列化的,使用where进行限制
 */
pub fn my_serialize<T:?Sized>(value:&T)->Vec<u8>
    where T: Serialize,{
    let seialized=bincode::serialize(value).unwrap();
    seialized
}

/**
 * 反序列化
 */
pub fn my_deserialize<'a,T>(bytes:&'a[u8])->T
    where T:Deserialize<'a>{
    let deserialized=bincode::deserialize(bytes).unwrap();
    return deserialized;
}
/**
 * 对象转hash
 *
 */
pub fn get_hash(value:&[u8])->String{
    let mut hasher=Sha3::sha3_256();
    hasher.input(value);
    hasher.result_str()
}

#[derive(Serialize, Deserialize,Debug,PartialEq,Eq)]
struct Point{
    x:i32,
    y:i32,
}

#[cfg(test)]
mod tests {
    use crate::coder::Point;
    use crate::coder::{my_serialize,my_deserialize};
    #[test]
    fn coders_works() {
        let point=Point{x:1,y:2};
        let se=my_serialize(&point);
        let de=my_deserialize(&se);
        assert_eq!(point,de);
    }
}

在utils为了完成数据的序列化和反序列化,使用了第三方bincode、serde、rust-crypto模块,如下Cargo.toml配置。

[package]
name = "utils"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bincode = "1.3.3"
serde = {version="1.0.136", features=["derive"]}
rust-crypto = "0.2"

在lib.rs中暴露编写的coder.rs模块。

pub mod coder;

在测试运行的main模块中引入core模块。

[package]
name = "main"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
core={path="../core"}

运行方法:

use core::blockchain;

fn main() {
    let mut bc=blockchain::BlockChain::new_blockchain();
    bc.add_block("a->b: 5btc".to_string());
    bc.add_block("b->c: 10btc".to_string());

    for b in bc.blocks{
        println!("++++++++++++++++++++++++++++++++++++++++");
        println!("{:#?}",b);
        println!("")
    }
}

运行结果

rust简单的区块链

链接