С технической точки зрения блокчейн — это децентрализованная одноранговая распределенная база данных, которая обеспечивает конечную согласованность. Давайте сначала реализуем блок и блокчейн.


блокировать

Блоки хранят достоверную информацию в блокчейне, такую ​​как транзакции. В этой части мы сначала реализуем простой блок и блокчейн, строим фреймворк, а затем постепенно улучшаем его по мере добавления новых функций.


заголовок блока

#[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