skka3134

skka3134

email
telegram

用Rust開發一個簡單的區塊鏈

一個區塊鏈的簡單結構,可以簡單理解為無數這樣的區塊像鏈條一樣連接起來組成了區塊鏈。
image

image
其中綠色部分叫做區塊頭,包含(pre hash,tx hash,time)
黑色部分和藍色部分叫做區塊體,包含(hash,transaction)

其中 pre hash 是上一個區塊的 hash
time 代表交易時間,時間戳
tx hash 用來保證數據不被串改,每個區塊的數據理論上是可以串改的,但是改了之後 hash 就對不上了。
transaction 即交易信息
最後是整個區塊的哈希值,該值相當於每個區塊的標識,同樣的,只要改了區塊中的一個數據,哈希值就會發生改變。

上代碼!!!

1. 首先我們需要使用包有,打開終端

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

2. 包 serde 是用來序列化和反序列化,序列化和反序列化是非常通用的功能,在網絡傳輸,數據存儲上極其常見的。序列化和反序列化的通用解釋是:seriallization 序列化 : 將對象轉化為便於傳輸的格式, 常見的序列化格式:二進制格式,字節數組,json 字符串,xml 字符串。 deseriallization 反序列化:將序列化的數據恢復為對象的過程。
包 bincode,是二進制的編碼格式。
包 crypto,是求 hash 的
包 chrono,是求時間戳的

3. 在頂端添加下面代碼

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

4. 定義區塊頭

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

5. 定義區塊

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

6. 使用剛才添加的包,去寫兩個一個序列化,一個反序列化的方法。

//序列化
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
}

7. 使用包 rust-crypto,去求 hash

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

8. 為之前定義的 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. 定義區塊鏈

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. 定義主方法

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!("");
    }
}

最後代碼應該是這樣的。

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 一下,效果
image
如果要模擬挖礦,用 sleep 休眠個 10s 左右

載入中......
此文章數據所有權由區塊鏈加密技術和智能合約保障僅歸創作者所有。