一個區塊鏈的簡單結構,可以簡單理解為無數這樣的區塊像鏈條一樣連接起來組成了區塊鏈。
其中綠色部分叫做區塊頭,包含(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 一下,效果
如果要模擬挖礦,用 sleep 休眠個 10s 左右