~目次~
- はじめに
- p2pネットワーク
- ブロックチェーン ← とりあえずブロックチェーンを知りたい方はここ!
- トランザクション
- ブロックチェーンの実装(JavaScript・Unity・Python)
- 参考文献
1. はじめに
ブロックチェーン技術に関する研究に没頭している大学生です。ブロックチェーン技術を勉強していて思うことは、ほんとに様々な技術が使われているということです!
多すぎて、忘れないためにも整理をしたくて、ここにまとめていこうと思いました。
ブロックチェーンは改竄することが非常に困難ということや、オープンで今までの履歴が全部見れる、管理者がいないなどがありますが、その細かな仕組みをこの記事に書いていきます。
上の図は、ブロックチェーン技術における全体的な流れを簡単に表したものになります。
この記事では、ビットコインをベースに考えていき、p2pネットワーク、ブロックチェーン、トランザクションといった感じで大きく三つに分けて、まとめていきたいと思います。最後には基本的なブロックチェーンの実装もしていきたいです。
そして、今後もブロックチェーン技術を勉強していく度に、この記事の更新をしていきたいと思います!
chainFlyerではビットコインのブロックチェーンの全てを確認することができます。トランザクションの中身や、ブロックが実際に生成されているところを見るだけでも楽しいです(^^)
2. p2pネットワーク
- p2pネットワークとは、ネットワークに参加しているコンピュータがそれぞれ同等の立場を持ち、平等で、特別なノードがなく、すべてのノードがネットワークサービスを提供する負荷を分担しています。
2-1. ノード
- フルノード
- 全てのトランザクションを含む、完全なブロックチェーンを管理しています。
- SPVノード
- ブロックチェーンの一部の管理のみを行います。
- ディスク容量や計算速度が限られているスマートフォンやタブレット、組み込みシステムなどのデバイス上で動作するように設計されています。
- マイナー、ウォレット、ルーティングノード
2-2. コンセンサスアルゴリズム
ブロックチェーンは管理者がいないということですが、具体的に言うと、管理者が不特定であるということです。では、どのように管理者を決めているのでしょうか。
その管理者を決める仕組みのことをコンセンサスアルゴリズムと言います。いくつか種類があります。
2-2-1. PoW(Proof of Work)
-
仕事量(CPUの計算量)に応じて、その**「誰か」に承認権を与えるという仕組みです。この作業のことをマイニングと言います。これを採用している代表的な仮想通貨はビットコイン**などです。
-
マイニング
- 暗号通貨の取引承認に必要となる複雑な計算(コンピューター演算)作業に協力し、その成功報酬として新規に発行された暗号通貨を得ることです。
- ある特定の値(ハッシュ値)を算出するためにナンスの計算をし続ける作業のことです。
こちらの「PoWにおけるマイニングのプログラムを作ってみた」の記事で、マイニングの仕組みとそのプログラムを説明しています。ぜひ参照してみてください!
2-2-2. PoS(Proof of Stake)
- CPUの処理能力に関係なく、通貨の保有量と通貨の保有期間によって、承認権を与える仕組みです。これを採用している代表的な仮想通貨はイーサリアムなどです。
- PoSにおけるマイニングとは、**Minting(forge、鋳造)**と呼ばれています。
2-2-3. PoI(Proof of Importance)
- 通貨の保有量にプラスして取引回数や取引量など、複数の指標から重要度によって、承認権を与える仕組みです。これを採用している代表的な仮想通貨はNEMなどです。
- PoIにおけるマイニングとは、**ハーべスティング(収穫)**と呼ばれています。
2-2-4. PoC(Proof of Consensus)
- 承認権を特定のノード(パソコン)のみに限定する仕組みです。これを採用している代表的な仮想通貨はリップルなどです。
3. ブロックチェーン
とりあえずって方はここだけでも...!!
この部分がブロックチェーンにおいて最も重要な部分になります。
ブロックには複数のトランザクションがあり、またヘッダというものがあります。ヘッダには、その複数のトランザクションの圧縮データや、直前ブロックの圧縮データ、ナンスというものがあります。ブロック生成者(マイナー)は既定のハッシュ値を算出するためにナンスの計算をし続けます(マイニング)。既定のハッシュ値を算出することができれば、ブロックを生成することができます。
3-1. 改ざんが非常に困難な理由
ブロックチェーンの改ざん方法は、他のブロック生成者(マイナー)より早く、規定のハッシュ値を算出し続け、正当なブロックチェーンより長いブロックチェーンを作ることです。
しかし、これらの行為は現実的に不可能であるため、改ざんは非常に困難だということが言えます。
この部分だけ読んでもらえれば十分まであります...!!(笑)
3-2. genesisブロック
- ブロックチェーンの最初のブロックです。
- ブロックチェーン上のすべてのブロックの祖先であり、どのブロックからブロックチェーンを過去に遡っても、最終的に行き当あるものです。
3-3. ブロック
3-3-1. ハッシュ関数
- ハッシュ値は元のデータが同じであれば同じ値になりますが、元のデータが1ビットでも異なると全く異なる値になります。また、ハッシュ値から入力データを計算することや推測することは困難であるという性質を備えています。
- RIPEMD160(RACE Integrity Primitives Evaluation Message Digest)
- どんな入力データであっても長さが160ビット(20バイト)のハッシュ値を出力します。
- SHA256(Secure Hash Algorithm)
pythonを使った実行例
Python 3.7.1
>>> import hashlib
>>> print(hashlib.sha256("Blockchain".encode("utf-8")).hexdigest())
625da44e4eaf58d61cf048d168aa6f5e492dea166d8bb54ec06c30de07db57e1
3-3-2. タイムスタンプ技術
- タイムスタンプ局(TSA: Time-Stamping Authority)と呼ばれる第三者機関が、利用者が持つデジタルデータがある時刻以前に存在したことを証明する技術です。
- タイムスタンプ局と時刻配信局の役割は混同されがちですが、利用者のデータに対する存在時刻証明はタイムスタンプ局が担い、その時刻の正確さを担保する役割を時刻配信局が担うことになります。
- ブロックチェーンは1つのコンピュータの時刻を記録をするのではなく、複数のパソコンで同時に記録を行います。そのため、パソコンごとの時刻が少しずつずれていくといった現象が起きてしまいます。ただブロックチェーンは時刻の正確さよりも、取引情報の順序関係の維持の方が大切です。
3-3-3. nonce(number used once)
- 使い捨てのランダムな32ビットの値です
- マイニングをする際に、規定のハッシュ値を算出するために使います。
3-3-4. マークルツリー
4. トランザクション
- 価値の移転を表した、署名されたデータ構造のことです。簡単にいうと、取引に関する情報が記述してあります。
4-1. UTXO(unspent transaction output)
-
中身はインプットとアウトプットという二種類の形で構成されています。インプットには、今までのブロックのトランザクションの未検証のアウトプットが入ります。アウトプットは実際に送金する相手のアドレスへの送金情報が入ります。
-
generationトランザクション・coinbaseトランザクション
- このトランザクションは特別なトランザクションであり、マイニングの努力に対する報酬となるものです。
- インプット部分に未検証のトランザクションは入らず、coinbaseと呼ばれる何もないところから、お金を生み出すたった一つのインプットが入ります。
-
ビットコインアドレス
- 誰にでも共有され得る、数字と文字で構成された文字列です。また、公開鍵から生成され、1から始まる文字列でもあります。
- 「Base58Check」と呼ばれる形にエンコードされた状態で使われます。
4-2. トランザクションプール
- **未検証のトランザクション(UTXO)**の一時的なリスト
- マイナーがトランザクションプールにある手数料の高いトランザクションから取り出していき、ブロックが生成されたタイミングで、送金が完了したことになります。
4-3. 電子署名
4-3-1. 公開鍵暗号方式
- 公開鍵
- 秘密鍵
4-3-2. デジタル署名
- 認証
- 完全性
- 否認防止
5. ブロックチェーンの実装
5-1. JavaScriptでの実装
JavaScriptで基本的なブロックチェーンを実装してみます。
5-1-1. node.jsをダウンロード
私は推奨版の10.15.0LTSの方をダウンロードしました。
5-1-2. crypto-jsのインストール
ハッシュ関数(SHA256)を使うためにインストールします。
npm install crypto-js
5-1-3. コーディング(JavaScript)
こちらが完成版のプログラムになります。
const SHA256 = require('crypto-js/sha256');
class Block {
constructor(index, timestamp, data, previousHash = '') {
this.index = index;
this.previousHash = previousHash;
this.timestamp = timestamp;
this.data = data;
this.hash = this.calculateHash();
}
calculateHash() {
return SHA256(this.index + this.previousHash + this.timestamp + JSON.stringify(this.data)).toString();
}
}
class Blockchain {
constructor() {
this.chain = [ this.createGenesisBlock() ];
}
createGenesisBlock() {
return new Block(0, "2019/01/01", "Genesis block", "0");
}
getLatestBlock() {
return this.chain [this.chain.length - 1];
}
addBlock(newBlock) {
newBlock.previousHash = this.getLatestBlock().hash;
newBlock.hash = newBlock.calculateHash();
this.chain.push(newBlock);
}
}
let coin = new Blockchain();
coin.addBlock(new Block(1, '2019/01/02', {amount: 10}));
coin.addBlock(new Block(2, '2019/01/03', {amount: 100}));
coin.addBlock(new Block(3, '2019/01/04', {amount: 1000}));
console.log(JSON.stringify(coin, null, 4));
5-1-4. 実行(JavaScript)
ここまで順調にいくと、ファイルはこんな感じになっています。
node blockchain.js
Node.jsのコマンドプロンプト上で上記のように実行します。
このように出力されていれば成功です!!
画像が見にくい場合は以下を参照してください。
{
"chain": [
{
"index": 0,
"previousHash": "0",
"timestamp": "2019/01/01",
"data": "Genesis block",
"hash": "eb0253d138e542de7114e11f53202dafb30771fce32a4c4e1e7d6cf0575d9a95"
},
{
"index": 1,
"previousHash": "eb0253d138e542de7114e11f53202dafb30771fce32a4c4e1e7d6cf0575d9a95",
"timestamp": "2019/01/02",
"data": {
"amount": 10
},
"hash": "9b65f59493ce9d6a70bb44f68f9dec09dfd60a066bc206bd0507a6bd33e63a9e"
},
{
"index": 2,
"previousHash": "9b65f59493ce9d6a70bb44f68f9dec09dfd60a066bc206bd0507a6bd33e63a9e",
"timestamp": "2019/01/03",
"data": {
"amount": 100
},
"hash": "62ee9707569c5bff2c60d0d13d5417d413e451d70f3de34a30d324de88a69c5b"
},
{
"index": 3,
"previousHash": "62ee9707569c5bff2c60d0d13d5417d413e451d70f3de34a30d324de88a69c5b",
"timestamp": "2019/01/04",
"data": {
"amount": 1000
},
"hash": "5a4c68aa1a10c4d558e87cb6adf96769d00b42de56b6ed072e0d8e410429498d"
}
]
}
5-2. Unity(C#)での実装
Unityで基本的なブロックチェーンを実装してみます。
5-2-1. Unityのダウンロード
私は無償のPersonal版をダウンロードしました。
5-2-2. ハッシュ関数(sha256)
最初にusing System.Textを書いてあげると、下記の関数が使えるようになります。
これを使ってハッシュ化していきましょう!
//ハッシュ関数(SHA-256)
private static string sha256(string randomString)
{
var crypt = new System.Security.Cryptography.SHA256Managed();
var hash = new System.Text.StringBuilder();
byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString));
foreach (byte theByte in crypto)
{
hash.Append(theByte.ToString("x2"));
}
return hash.ToString();
}
5-2-3. コーディング(Unity)
ハッシュ関数(sha256)のコードも入れて、こちらが完成版のプログラムになります。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Text;
public class main : MonoBehaviour {
// Use this for initialization
void Start () {
BlockChain blockchain = new BlockChain();
blockchain.addBlock(new Block(1, BlockChain.chain[BlockChain._ChainCountNumber]._hash, "2019/01/02", "Transaction1"));
blockchain.addBlock(new Block(2, BlockChain.chain[BlockChain._ChainCountNumber]._hash, "2018/01/03", "Transaction2"));
for (int i = 0; i < BlockChain._ChainCountNumber + 1; i++)
{
BlockChain.chain[i].DebugStatus();
}
}
// Update is called once per frame
//void Update () {
//}
}
public class Block{
public int _index;
public string _previousHash;
public string _timestamp;
public string _data;
public string _hash;
public Block(int index, string previousHash, string timestamp, string data)
{
_index = index;
_previousHash = previousHash;
_timestamp = timestamp;
_data = data;
_hash = sha256(_index.ToString() + _previousHash + _timestamp + _data);
}
public void DebugStatus()
{
// string.Formatを使うと, + でつなげるよりも見た目わかりやすく文字を連結できる。
Debug.Log(string.Format("index; {0}, previousHash; {1}, timestamp; {2}, data; {3}, hash; {4}", _index, _previousHash, _timestamp, _data, _hash));
}
//ハッシュ関数(SHA-256)
private static string sha256(string randomString)
{
var crypt = new System.Security.Cryptography.SHA256Managed();
var hash = new System.Text.StringBuilder();
byte[] crypto = crypt.ComputeHash(Encoding.UTF8.GetBytes(randomString));
foreach (byte theByte in crypto)
{
hash.Append(theByte.ToString("x2"));
}
return hash.ToString();
}
}
public class BlockChain{
public static int _ChainCountNumber = 0;
public static Block[] chain = new Block[100];
public BlockChain()
{
chain[_ChainCountNumber] = createGenesisBlock();
}
private Block createGenesisBlock()
{
return new Block(_ChainCountNumber, "0", "2019/01/01", "Genesis block");
}
public void addBlock(Block newBlock)
{
chain[++_ChainCountNumber] = newBlock;
}
}
5-2-4. 実行(Unity)
まず、Main Cameraにmain.csをつけてあげます。
次に実行をして、Consoleを見ると、画像のように出力されていれば、成功です!!
画像が見にくい場合は以下を参照してください。
index; 0, previousHash; 0, timestamp; 2019/01/01, data; Genesis block, hash; 14f026b78e06f95988ac3ee6f9dfba763fe871fe6b5ab04b83f181b6e384c785
UnityEngine.Debug:Log(Object)
Block:DebugStatus() (at Assets/main.cs:47)
main:Start() (at Assets/main.cs:18)
index; 1, previousHash; 14f026b78e06f95988ac3ee6f9dfba763fe871fe6b5ab04b83f181b6e384c785, timestamp; 2019/01/02, data; Transaction1, hash; 5c95040f6162d136820304e97eddd3a752523117f3d6fa3063d3fa37e2a0d269
UnityEngine.Debug:Log(Object)
Block:DebugStatus() (at Assets/main.cs:47)
main:Start() (at Assets/main.cs:18)
index; 2, previousHash; 5c95040f6162d136820304e97eddd3a752523117f3d6fa3063d3fa37e2a0d269, timestamp; 2018/01/03, data; Transaction2, hash; c05679467545832fcaf70b1fa6ca4e0d676f6c7dae08751223c2df1df22e55b0
UnityEngine.Debug:Log(Object)
Block:DebugStatus() (at Assets/main.cs:47)
main:Start() (at Assets/main.cs:18)
5-3. Pythonでの実装
Pythonで基本的なブロックチェーンを実装してみます。
5-3-1. Pythonのインストール
2つの方法で説明します。
1つ目の方法はPython公式サイトからインストーラーをダウンロードしてください。
2つ目の方法はVisual Studio 2017 Community版のダウンロードになります。
私はVisual Studio 2017のコミュニティ版をダウンロードしました。
次にPythonで開発を行うために「Python開発」にチェックを入れて、ダウンロードします。
5-3-2. ハッシュ関数(sha256)
import hashlib
hashlibをimportすると、ハッシュ関数(sha256)が使えるようになります。
5-3-3. コーディング(Python)
import hashlibのコードも入れて、こちらが完成版のプログラムになります。
import hashlib
class Block:
def __init__(self, index, timestamp, data, previousHash = ""):
self.index = index
self.previousHash = previousHash
self.timestamp = timestamp
self.data = data;
self.hash = self.calculateHash()
def calculateHash(self):
return (hashlib.sha256((str(self.index) + str(self.previousHash) + str(self.timestamp) + str(self.data)).encode('utf-8')).hexdigest())
def setdict(self):
d = { "index":self.index, "previousHash":self.previousHash, "timestamp":self.timestamp, "data":self.data, "hash":self.hash}
return d
class Blockchain:
def __init__(self):
self.chain = [self.createGenesisBlock().setdict()]
def createGenesisBlock(self):
return Block(0, "2019/01/01", "Genesis block","0")
def getLatestBlock(self):
return self.chain[len(self.chain) - 1]
def addBlock(self, newBlock):
newBlock.previousHash = self.getLatestBlock()["hash"]
newBlock.hash = newBlock.calculateHash()
self.chain.append(newBlock.setdict())
def main():
coin = Blockchain()
coin.addBlock(Block(1, "2019/01/02", "amount: 10"))
coin.addBlock(Block(2, "2019/01/03", "amount: 100"))
coin.addBlock(Block(3, "2019/01/04", "amount: 1000"))
print(coin.chain)
if __name__ == '__main__':
main()
5-3-4. 実行(Python)
実行して、画像のように出力されていれば、成功です!!
画像が見にくい場合は以下を参照してください。
[
{'index': 0,
'previousHash': '0',
'timestamp': '2019/01/01',
'data': 'Genesis block',
'hash': '14f026b78e06f95988ac3ee6f9dfba763fe871fe6b5ab04b83f181b6e384c785'},
{'index': 1,
'previousHash': '14f026b78e06f95988ac3ee6f9dfba763fe871fe6b5ab04b83f181b6e384c785',
'timestamp': '2019/01/02',
'data': 'amount: 10',
'hash': 'b24262bd2616f9a54814eaa758b7a90cb4358dd773ffc5f0328af2e513f726f3'},
{'index': 2,
'previousHash': 'b24262bd2616f9a54814eaa758b7a90cb4358dd773ffc5f0328af2e513f726f3',
'timestamp': '2019/01/03',
'data': 'amount: 100',
'hash': '751b60524211e1b90716371f480fbb930861a8b8129c95d97a2c808225668ae2'},
{'index': 3,
'previousHash': '751b60524211e1b90716371f480fbb930861a8b8129c95d97a2c808225668ae2',
'timestamp': '2019/01/04',
'data': 'amount: 1000',
'hash': '7f7cfce99623b93ca4681a2fce6408d63874498d9c44a90477f87367292a53a1'}
]
6. 参考文献
-
「ゼロから創る暗号通貨」濵津 誠 (2018年9月7日)
-
「ブロックチェーン技術の教科書」佐藤 雅史 長谷川 佳祐 佐古 和恵 並木 悠太 梶ヶ谷 圭祐 松尾信一郎 (2018年4月23日)
-
「Mastering Bitcoin ~ビットコインとブロックチェーン 暗号通貨を支える技術~」 アンドレス・M・アントオプロス (2016年7月21日)
-
「Mastering Bitcoin ~ビットコインとブロックチェーン 暗号通貨を支える技術~ (コンサイス版)」 アンドレス・M・アントオプロス (2018年4月18日)
-
C# ハッシュ関数の参考 → 「c# 復号 ファイル - Sha256で文字列をハッシュする」
-
(JavaScriptでブロックチェーンを作ってみた)「大学生Webエンジニアの記録」(2018年10月2日)
-
「ブロックチェーン -相互不信が実現する新しいセキュリティ-」岡嶋 裕史 (2019年1月20日)