С технической точки зрения блокчейн — это децентрализованная одноранговая распределенная база данных, которая обеспечивает конечную согласованность. Давайте сначала реализуем блок и блокчейн.
блокировать
Блоки хранят достоверную информацию в блокчейне, такую как транзакции. В этой части мы сначала реализуем простой блок и блокчейн, строим фреймворк, а затем постепенно улучшаем его по мере добавления новых функций.
заголовок блока
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct BlockHeader {
timestamp: i64,
prev_hash: String,
nonce: usize,
}
-
отметка времени: отметка времени
-
prev_hash: значение хеш-функции предыдущего блока.
-
nonce: случайное число, используемое для вычисления доказательства работы
блокировать
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq)]
pub struct Block {
header: BlockHeader,
data: String,
hash: String,
}
-
заголовок: заголовок блока
-
data: данные, хранящиеся в блоке.Когда функция транзакций будет реализована позже, это поле будет изменено на набор транзакций.
-
hash: Хэш-значение блока
Значение хеш-функции вычисляется и сохраняется в каждом блоке, а хэш предыдущего блока сохраняется в заголовке блока, образуя таким образом цепочку блоков. Как показано на рисунке:
Рассчитать хэш-значение
Мы можем хэшировать заголовок блока, потому что заголовок блока содержит всю информацию о блоке, а хэш-значение транзакции будет добавлено в заголовок блока позже.
Сначала используйте библиотеки serde и bincode для сериализации заголовка блока в байты, а затем используйте SHA256 для вычисления хеш-значения.
pub fn serialize<T>(data: &T) -> Result<Vec<u8>, BlockchainError>
where
T: Serialize + ?Sized
{
Ok(bincode::serialize(data)?)
}
pub fn hash_to_str(data: &[u8]) -> String {
let mut hasher = Sha3::sha3_256();
hasher.input(data);
hasher.result_str()
}
Создавайте новые блоки и внедряйте блоки генезиса
Генезисный блок — это первый блок в цепочке блоков, поэтому prev_hash в заголовке блока не имеет значения.
pub fn new(data: &str, prev_hash: &str) -> Self {
let mut block = Block {
header: BlockHeader {
timestamp: Utc::now().timestamp(),
prev_hash: prev_hash.into(),
nonce: 0,
},
data: data.into(),
hash: String::new(),
};
block.set_hash();
block
}
pub fn create_genesis_block() -> Self {
Self::new("创世区块", "")
}
блокчейн
Теперь мы сначала сохраняем блок в памяти, а затем блок будет храниться в базе данных KV.
pub struct Blockchain {
blocks: Vec<Block>,
height: usize,
}
-
блоки: коллекция блоков
-
высота: высота блокчейна, то есть количество блоков.
добыча
это добавить блок в цепочку
pub fn mine_block(&mut self, data: &str) {
let prev_block = self.blocks.last().unwrap();
let block = Block::new(data, prev_block.get_hash().as_str());
self.blocks.push(block);
self.height += 1;
}
Создайте блокчейн и присоединитесь к блоку
let mut bc = Blockchain::new();
bc.mine_block("Justin -> Bob 2 btc");
bc.mine_block("Justin -> Bruce 2 btc");
bc.blocks_info();
Результаты:
RUST_LOG=info cargo run --example gen_bc --quiet
INFO blockchain_rust_part_1::blocks::blockchain: Block {
header: BlockHeader {
timestamp: 1650188197,
prev_hash: "",
nonce: 0,
},
data: "创世区块",
hash: "dc7e47a45b9b898269efbc4e05cff5d2c8c9dac17cd181451471e62cdcd646c6",
}
INFO blockchain_rust_part_1::blocks::blockchain: Block {
header: BlockHeader {
timestamp: 1650188197,
prev_hash: "dc7e47a45b9b898269efbc4e05cff5d2c8c9dac17cd181451471e62cdcd646c6",
nonce: 0,
},
data: "Justin -> Bob 2 btc",
hash: "8620a3e7965c71ccf391898bb53a374db8d133a2c7dcbfa05cea9b83a06c04dc",
}
INFO blockchain_rust_part_1::blocks::blockchain: Block {
header: BlockHeader {
timestamp: 1650188197,
prev_hash: "8620a3e7965c71ccf391898bb53a374db8d133a2c7dcbfa05cea9b83a06c04dc",
nonce: 0,
},
data: "Justin -> Bruce 2 btc",
hash: "3618c57b1aec52b56f820bc20a03f171174a059c5a982e486e0975c1eccbaa12",
}
Инженерное сооружение

Полный код:
https://github.com/Justin02180218/blockchain_rust