javascriptでブロックチェーンをつくってみよう - 2 ブロックチェーンの実装
ビットコインをJavascriptで実装しながら理解しましょう。
前回までにブロックの実装を行ないました。今回はブロックをチェーンでつなげるブロックチェーンの実装を行ないます。
開発の流れ
前回までの状態を再現
必要な場合は、前回の状態を再現しましょう。
$ git clone https://github.com/mizumotok/blockchain-js.git $ cd blockchain-js $ git checkout 01_block
ブロックチェーンの実装
ブロックチェーンはブロックを配列で持ちます。最初のブロックはgenesisブロックなので、constructorで持たせておけばいいです。
src/blockchain/blockchain.js
// @flow import Block from './block'; class Blockchain { chain: Array<Block>; constructor() { this.chain = [Block.genesis()]; } } export default Blockchain;
src/blockchain/index.js
import Blockchain from './blockchain'; import Block from './block'; export default Blockchain; export { Block };
新しいブロックはマイナーがつくってそれをブロックチェーンについていくのですが、追加される際にそのブロックは追加するのに適当か検証しましょう。
src/blockchain/blockchain.js
addBlock(block: Block): bool { if (!this.canAddBlock(block)) { return false; } this.chain.push(block); return true; } canAddBlock(block: Block): bool { const lastBlock = this.chain[this.chain.length - 1]; return block.prevHash === lastBlock.hash() && block.timestamp > lastBlock.timestamp && block.isValid(); }
ブロックチェーンの最後のブロックのハッシュ値は次のブロックを作るときに使われますので、簡単に取り出せるようにしておくとよいですね。
src/blockchain/blockchain.js
lastHash(): string { return this.chain[this.chain.length - 1].hash(); }
テスト
今回作成したメソッド(コンストラクタ、addBlock、canAddBlock、lastHash)のテストを用意しておけば完璧です。
src/__tests__/blockchain/blockchain.test.js
// @flow import Blockchain, { Block } from '../../blockchain'; describe('Blockchain', () => { let blockchain; let newBlock; beforeEach(() => { blockchain = new Blockchain(); newBlock = new Block(new Date(), blockchain.chain[0].hash(), 256, 0, []); }); it('初期値はgenesis blockのみ', () => { expect(blockchain.chain).toHaveLength(1); const block = Block.genesis(); expect(blockchain.chain[0].hash()).toBe(block.hash()); }); it('canAddBlock test', () => { const olderBlock = new Block(-1, blockchain.chain[0].hash(), 256, 0, []); expect(blockchain.canAddBlock(olderBlock)).toBe(false); const wrongHashBlock = new Block(new Date(), 'xxxx', 256, 0, []); expect(blockchain.canAddBlock(wrongHashBlock)).toBe(false); const inValidBlock = new Block(new Date(), blockchain.chain[0].hash(), 0, 0, []); expect(blockchain.canAddBlock(inValidBlock)).toBe(false); expect(blockchain.canAddBlock(newBlock)).toBe(true); }); it('addBlock test', () => { const inValidBlock = new Block(new Date(), blockchain.chain[0].hash(), 0, 0, []); let result = blockchain.addBlock(inValidBlock); expect(result).toBe(false); expect(blockchain.chain).toHaveLength(1); result = blockchain.addBlock(newBlock); expect(result).toBe(true); expect(blockchain.chain).toHaveLength(2); expect(blockchain.chain[0].hash()).toBe(blockchain.chain[1].prevHash); }); it('lastHash test', () => { const genesis = Block.genesis(); expect(blockchain.lastHash()).toBe(genesis.hash()); blockchain.addBlock(newBlock); expect(blockchain.lastHash()).toBe(newBlock.hash()); }); });
ここまでのソースはGitHubの02_blockchainブランチに公開しています。
まとめ
今回はブロックチェーンの実装をしました。ブロックを配列で持たせ、ブロック追加時にブロックの検証をするようにしました。また最後のブロックのハッシュ値を簡単に出せるメソッドを用意しました。
次回はブロックをマイニングして生成する、マイナーの実装をします。
GitHub
GitHub - mizumotok/blockchain-js
- 作者: アンドレアス・M・アントノプロス,今井崇也,鳩貝淳一郎
- 出版社/メーカー: エヌティティ出版
- 発売日: 2016/07/14
- メディア: 大型本
- この商品を含むブログ (7件) を見る