Daily Archive2022-02-05

Blockchain in Rust

ブロックチェーンのしくみをもっと実装ベースで理解したいといろいろ調べていたところ、まさにそのものである学習用のRustを使ったコンパクトに実装されたコードとそのデモ動画があったため試してみました。(Solanaのような新しいブロックチェーン開発で使うRustとはまた別の話。いづれテスト予定)

https://github.com/GeekLaunch/blockchain-rust

参考書籍: 「ビットコインとブロックチェーン」(NTT出版)

参考動画: (最下部にリンク)

block作成、blockchain作成、トランザクション作成の機能がそれぞれモジュール化されており、main.rsファイルでそれらを利用して自由に作ることができるようになっています。

main.rs

use blockchainlib::*; fn main () { let difficulty = 0x000fffffffffffffffffffffffffffff; let mut genesis_block = Block::new(0, now(), vec![0; 32], vec![ Transaction { inputs: vec![ ], outputs: vec![ transaction::Output { to_addr: "Alice".to_owned(), value: 60, }, transaction::Output { to_addr: "Bob".to_owned(), value: 30, }, ], }, ], difficulty); genesis_block.mine(); let mut last_hash = genesis_block.hash.clone(); let mut blockchain = Blockchain::new(); blockchain.update_with_block(genesis_block).expect("Failed to add genesis block"); println!("{:?}", blockchain); let mut h = last_hash.clone(); let mut block = Block::new(1, now(), last_hash, vec![ Transaction { inputs: vec![ ], outputs: vec![ transaction::Output { to_addr: "Min1".to_owned(), value: 20, }, ], }, Transaction { inputs: vec![ blockchain.blocks[0].transactions[0].outputs[0].clone(), ], outputs: vec![ transaction::Output { to_addr: "Alice".to_owned(), value: 40, }, transaction::Output { to_addr: "Bob".to_owned(), value: 10, }, ], }, ], difficulty); block.mine(); last_hash = block.hash.clone(); blockchain.update_with_block(block).expect("Failed to add block"); println!("{:?}", blockchain); let mut block2 = Block::new(2, now(), last_hash, vec![ Transaction { inputs: vec![ ], outputs: vec![ transaction::Output { to_addr: "Min2".to_owned(), value: 30, }, ], }, Transaction { inputs: vec![ blockchain.blocks[1].transactions[0].outputs[0].clone(), ], outputs: vec![ transaction::Output { to_addr: "Alice".to_owned(), value: 9, }, ], }, ], difficulty); block2.mine(); last_hash = block2.hash.clone(); blockchain.update_with_block(block2).expect("Failed to add block"); println!("{:?}", blockchain); }
Code language: PHP (php)

実行結果

デモとは違い出力内容をかなり変えています。(下記変更)

blockchain.rs

#[derive(Debug)] pub struct Blockchain { pub blocks: Vec<Block>, unspent_outputs: HashSet<Hash>, }
Code language: HTML, XML (xml)
println!("coinbase output value: {:?} total fee: {:?}", coinbase.output_value(), total_fee); if coinbase.output_value() < total_fee { return Err(BlockValidationErr::InvalidCoinbaseTransaction); } else { block_created.extend(coinbase.output_hashes()); }
Code language: PHP (php)

ブロックチェーンを更新する際に、コインの計算が合わないとエラーになります。

最初はジェネシスブロックで、そこに追加していきます。それぞれのブロックの最初のトランザクションはコインベーストランザクション(INPUTなし)で、マイニングに勝ったマイナーによっておかれることを表現しています。unspent_outputs: にあるハッシュを見てみると、消費されたアウトプットは次になくなっていることも確認できます。

ブロックチェーンの基礎を勉強する教材としてとても素晴らしいため、自分用メモとして残しておきたいと思いました。