一个区块链的简单结构,可以简单理解为无数这样的区块像链条一样连接起来组成了区块链。
其中绿色部分叫做区块头,包含(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 左右