如何使用 Rust 從頭構(gòu)建一個(gè)區(qū)塊鏈
英文原文鏈接 https://coinsbench.com/how-to-build-a-blockchain-from-scratch-in-rust-9cedb59f8897
2021年對(duì)加密貨幣、NFT和去中心化應(yīng)用程序(DAPPs)來(lái)說(shuō)是重要的一年,2022年將更重要。區(qū)塊鏈?zhǔn)撬羞@些技術(shù)背后的底層技術(shù)。
區(qū)塊鏈技術(shù)有潛力改變我們生活的幾乎每一個(gè)方面,包括金融行業(yè)蒸其、旅游和出行、基礎(chǔ)設(shè)施库快、醫(yī)療保健摸袁、公共部門、零售缺谴、農(nóng)業(yè)和采礦但惶、教育耳鸯、通信、娛樂等膀曾。
世界上每個(gè)我崇拜的聰明人都有一個(gè)原因县爬。他們明白這是第四次工業(yè)革命的驅(qū)動(dòng)力: 蒸汽機(jī)、電力添谊,然后是微芯片——第四次是區(qū)塊鏈和加密貨幣财喳。 —— 布洛克 皮爾斯(Brock Pierce)
什么是區(qū)塊鏈?
區(qū)塊鏈?zhǔn)强琰c(diǎn)對(duì)點(diǎn)網(wǎng)絡(luò)的去中心化交易賬本斩狱,您也可以將區(qū)塊鏈看作是不可變的去中心化數(shù)據(jù)庫(kù)耳高。一個(gè)區(qū)塊鏈可以從根本上分解為幾個(gè)組件,如節(jié)點(diǎn)所踊、交易泌枪、區(qū)塊、鏈和共識(shí)協(xié)議(工作證明秕岛、權(quán)益證明碌燕、歷史證明)。
如果你像我一樣继薛,喜歡通過(guò)實(shí)戰(zhàn)來(lái)學(xué)習(xí)修壕。那么本文通過(guò)使用Rust構(gòu)建一個(gè)區(qū)塊鏈,會(huì)讓你對(duì)區(qū)塊鏈如何工作的有個(gè)基本概念遏考。
聽起來(lái)還不錯(cuò)是吧慈鸠?那讓我們開始吧。
現(xiàn)在開始
讓我們從創(chuàng)建一個(gè)新的Rust項(xiàng)目開始:
cargo +nightly new blockchain
然后切換到你剛創(chuàng)建的目錄中:
cd blockchain
然后為構(gòu)建區(qū)塊鏈添加必要的依賴包:
[dependencies]
chrono = "0.4"
serde = { version = "1.0.106", features = ["derive"] }
serde_json = "1.0"
sha2 = "0.10.0"
下一步灌具,創(chuàng)建 models 目錄來(lái)保存你的區(qū)塊鏈的大部分邏輯青团。目錄中添加兩個(gè)文件 blockchain.rs
和 block.rs
。
兩個(gè)文件中引入下面的依賴包并保存他們:
// Blockchain.rs
use chrono::prelude::*;
// internal module
use super::block::Block;
// Block.rs
use super::blockchain::Blockchain;
use chrono::prelude::*;
use sha2::{Sha256, Digest};
use serde::{Deserialize, Serialize};
可能你已經(jīng)注意到在 blockchain.rs
文件中引入了 use super::block::Block;
咖楣, 這里我們只是引入了 block.rs
文件中的結(jié)構(gòu)體壶冒,不用擔(dān)心后面我會(huì)解釋。
在引入必要的依賴包之后截歉,讓我們?cè)?blockchain.rs
文件中定義一個(gè) Blocks
類型:
type Blocks = Vec<Block>;
下一步,在 blockchain.rs
中創(chuàng)建 Blockchain
類型烟零,并添加一個(gè)空的實(shí)現(xiàn):
// Blockchain 代表區(qū)塊鏈的結(jié)構(gòu)體
#[derive(Debug)]
pub struct Blockchain {
// 添加到鏈中的第一個(gè)區(qū)塊
pub genesis_block: Block,
// 存儲(chǔ)區(qū)塊
pub chain: Blocks,
// 驗(yàn)證一個(gè)區(qū)塊需要的最小工作量
pub difficulty: usize,
}
impl Blockchain {}
下一步瘪松, 在 block.rs
文件中定義 Block
類型,并添加空的實(shí)現(xiàn):
// Block 代表區(qū)塊鏈中的區(qū)塊結(jié)構(gòu)體
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Block {
// 保存的當(dāng)前區(qū)塊的索引
pub index: u64,
// 當(dāng)前區(qū)塊的創(chuàng)建時(shí)間
pub timeStamp: u64,
// 區(qū)塊的工作證明
pub proof_of_work: u64,
// 前一個(gè)區(qū)塊哈希
pub previous_hash: String,
// 當(dāng)前區(qū)塊哈希
pub hash: String
}
impl Block {}
創(chuàng)建創(chuàng)世區(qū)塊
創(chuàng)世區(qū)塊是區(qū)塊鏈中創(chuàng)建的第一個(gè)區(qū)塊锨阿。接下來(lái)創(chuàng)建一個(gè)函數(shù)可以為我們的區(qū)塊鏈生成一個(gè)創(chuàng)世區(qū)塊宵睦,并返回一個(gè)新的 Blockchain
類型。
在 blockchain.rs
中添加我們的 Blockchain
實(shí)現(xiàn)墅诡,代碼如下:
imple Blockchain {
pub fn new(difficulty: usize) -> Self {
// 鏈中的第一個(gè)塊
let mut genesis_block = Block {
index: 0,
timestamp: Utc::now().timestamp_millis() as u64,
proof_of_work: u64::default(),
previous_hash: String::default(),
hash: String::default()
};
// 從創(chuàng)世鏈開始創(chuàng)建鏈
let mut chain = Vec::new();
chain.push(genesis_block.clone());
// 創(chuàng)建一個(gè)區(qū)塊鏈實(shí)例
let blockchain = Blockchain {
genesis_block,
chain,
difficulty
};
blockchain
}
}
上面的代碼主要實(shí)現(xiàn)了這些功能:
- 創(chuàng)建我們的
genesis_block
實(shí)例 - 將我們創(chuàng)建的
genesis_block
添加到Blockchain
類型的鏈中 - 返回一個(gè)
Blockchain
類型的實(shí)例
在我們創(chuàng)建的 genesis_block
實(shí)例中壳嚎,注意到我們?cè)O(shè)置 previous_hash 的值為空字符串(String::default()),這是因?yàn)閯?chuàng)世區(qū)塊是區(qū)塊鏈中的第一個(gè)區(qū)塊所以不存在上一個(gè)區(qū)塊。
還要注意烟馅,我們將 genesis_block
的哈希值設(shè)為一個(gè)空字符串("")说庭,這是因?yàn)槲覀冞€沒有為我們的創(chuàng)世區(qū)塊計(jì)算哈希值。
為區(qū)塊生成哈希值
哈希是根據(jù)當(dāng)前區(qū)塊的信息加密生成的郑趁。
在 block.rs
文件中為我們的區(qū)塊實(shí)現(xiàn)添加 calculate_hash()
函數(shù):
// 計(jì)算區(qū)塊哈希
pub fn calculate_hash(&self) -> String {
let mut block_data = self.clone();
block_data.hash = String::default();
let serialized_block_data = serde_json::to_string(&block_data).unwrap();
// 計(jì)算生成 SHA-256 哈希值
let mut hasher = Sha256::new();
hasher.update(serialized_block_data);
let result = hasher.finalize();
format!("{:x}", result)
}
上面的代碼中刊驴,實(shí)現(xiàn)了如下功能:
- 區(qū)塊數(shù)據(jù)轉(zhuǎn)為JSON格式
- 使用 SHA256 加密算法計(jì)算區(qū)塊數(shù)據(jù)的哈希
- 返回16進(jìn)制格式的哈希結(jié)果
創(chuàng)建一個(gè)新的區(qū)塊
很棒!我們已經(jīng)實(shí)現(xiàn)了創(chuàng)建創(chuàng)世區(qū)塊和計(jì)算區(qū)塊哈希的功能寡润。
現(xiàn)在讓我們?cè)?blockchain.rs 文件中給 Blockchain
類型的實(shí)現(xiàn)添加創(chuàng)建新區(qū)塊的功能:
pub fn add_block(&mut self, nonce: String) {
let new_block = Block::new(
self.chain.len() as u64,
nonce,
self.chain[&self.chain.len() - 1].previous_hash.clone()
);
new_block.mine(self.clone());
self.chain.push(new_block.clone());
println!("New block added to chain -> {:?}", new_block);
}
這里我們做了如下操作:
- 添加了
add_block
函數(shù)捆憎,形參是 &mut self(Blockchain
類型的實(shí)例) - 創(chuàng)建
Block
類型的實(shí)例 - 使用
Block
類型的挖礦函數(shù)挖崛出一個(gè)區(qū)塊哈希 - 將新區(qū)塊添加到區(qū)塊鏈中
接下來(lái)在 block.rs
文件中給 Block
類型實(shí)現(xiàn)添加如下代碼:
// 創(chuàng)建一個(gè)新區(qū)塊,會(huì)自動(dòng)計(jì)算并設(shè)置哈希
pub fn new(
index: u64,
previous_hash: String,
) -> Self {
// 當(dāng)前要?jiǎng)?chuàng)建的區(qū)塊
let mut block = Block {
index: 0,
timestamp: Utc::now().timestamp_millis() as u64,
proof_of_work: u64::default(),
previous_hash: String::default(),
hash: String::default(),
};
block
}
這里做了如下操作:
- 添加
new()
函數(shù)接收兩個(gè)參數(shù) index 和 previous_hash - 創(chuàng)建
Block
類型的實(shí)例 - 為我們的區(qū)塊生成區(qū)塊哈希
- 最后返回
Block
類型的實(shí)例
挖崛新區(qū)塊
我們已經(jīng)成功實(shí)現(xiàn)了創(chuàng)建一個(gè)新區(qū)塊梭纹。
讓我們繼續(xù)添加功能來(lái)挖崛新區(qū)塊躲惰。挖掘新區(qū)塊的過(guò)程包括生成一個(gè)以指定個(gè)數(shù)的0開頭的SHA256哈希,這將是挖掘新區(qū)塊時(shí)礦工必須解決的挖掘難度变抽。
接下來(lái)在 Block
類型的實(shí)現(xiàn)中添加一個(gè)新函數(shù)
// 挖崛區(qū)塊哈希
pub fn mine(&mut self, blockchain: Blockchain) {
loop {
if !self.hash.starts_with(&"0".repeat(blockchain.difficulty)) {
self.proof_of_work += 1;
self.hash = self.generate_block_hash();
} else {
break;
}
}
}
干得漂亮础拨,目前為止我們已經(jīng)實(shí)現(xiàn)了我們的區(qū)塊鏈,現(xiàn)在讓我們測(cè)試它瞬沦。
讓我們?cè)?models 目錄中新增 mod.rs
文件太伊,并寫入如下代碼:
pub mod block;
pub mod blockchain;
這里主要是將我們?cè)缧r(shí)候添加的 blockchain.rs
和 block.rs
文件在 main.rs 文件中可以公開訪問(wèn)。
現(xiàn)在給 main.rs 文件添加如下代碼:
mod models;
fn main() {
let difficulty = 1;
let mut blockchain = models::blockchain::Blockchain::new(difficulty);
models::blockchain::Blockchain::add_block(&mut blockchain);
}
小結(jié)一下
通過(guò)本文你已經(jīng)了解了如何使用 rust 從頭創(chuàng)建一個(gè)簡(jiǎn)單的區(qū)塊鏈逛钻。
我希望您喜歡閱讀本文僚焦,您可以在這里獲得這個(gè)Rust區(qū)塊鏈的完整源代碼。
任何問(wèn)題歡迎留言評(píng)論曙痘。