オルトコイン

ビットコインブロックチェーン技術をベースに作られたビットコイン以外のブロックチェーンシステム、通貨をオルトコインという。 通貨を目的にしたものをオルトコイン、通貨以外の目的としたものをオルトチェーン。

Colored Coin

Colored Coinは、ビットコインのscriptにOP_RETURNを書いて、株式証明、クーポン、不動産、日用品などのデータを書いて、通貨以外の用途に使うということでいいのかな?

気になったアルトコインをメモ

NameCoin

キーバリューの形で登録され、DNSの代替のように使われる。 Emailアドレス、暗号キー、SSL証明書、ファイル署名などなどのアプリケーションで使われている。

あんまり一般的にきかないけど、SSL証明書とかのPKI技術者なのでw

Ethereum

まあ、なんといってもアルトコインといえばEthereumでしょう。 チューリング完全な契約処理と執行を行うプラットフォーム

なんといっても、特徴は、ブロックチェーンに記録するのは、チューリング完全なコード contract ですよね。 contractは、データの保存、etherの支払い、受け取り、保存、長さ無制限の処理を実行できるっと。

ほぼほぼmastering bitocoinの読み込みは終わったんだけど、 もうちょっとbitocoinの勉強やプログラム作成を続けるかEthereum、スマートコントラクトの勉強に移るか、、 やっぱり、Ethereum、スマートコントラクトの勉強だよな。

ブロックのチェーンの組み立て

ブロックの組み立て

ビットコインは、3種類のブロックセットを持っている。

  • インチェーン 累積difficultyが最も多くなっているチェーン
  • (メインから枝分かれした)セカンダリチェーン ほとんど同時に同じブロック高を持つブロックが採掘された結果
  • 親がいないオーファンブロック

新しいブロックを受け取った時、ノードは、すでにあるブロックチェーンにブロックを追加する。 ノードは、ブロックの「previous block hash」フィールドを確認する。

新しいブロックがメインチェーン以外のチェーンを拡張する。その場合、ノードは、ブロックをセカンダリチェーンにくっつける。 そして、メインチェーンとセカンダリチェーンのdifficultyを比較する。もし、セカンダリチェーンのdifficultyがメインチェーンより上回ってる場合は、セカンダリチェーンをメインチェーンに切り替える。

親のブロックが見つからなかった場合は、オーファンブロックとして、プールしておく。

ノードは、どのチェーンが拡張されていくかを選ぶことで、「投票」していくことになる。

ブロックヘッダの構築

仕事が忙しくなりだして、いつのまにか3月に。。

ブロックヘッダのフォーマットは、前にも書いたように下のようになっているけど、ブロックヘッダについてもう一度まとめてみる。

 ブロックヘッダ(Block Header)フォーマット

サイズ フィールド名 説明
4バイト Version ソフトウェア・プロトコルバージョン情報
32バイト Previous Block Hash 親ブロックのハッシュ値
32バイト Merkle Root ブロックの全トランザクションに対するマークルツリーのルートハッシュ
4バイト TimeStamp ブロックの生成時刻
4バイト Difficulty Target ブロック生成時のproof of workのdifficulty
4バイト Nonce proof of workで用いるカウンタ
$ bitcoin-cli getblock 0000000000000c2e8d3c2a3f74e3006011cc1f4f43b122b587564ad99f3906f6
{
  "hash": "0000000000000c2e8d3c2a3f74e3006011cc1f4f43b122b587564ad99f3906f6",
  "confirmations": 80105,
  "strippedsize": 57982,
  "size": 58018,
  "weight": 231964,
  "height": 1377316,
  "version": 536870912,
  "merkleroot": "ab16d417f9dd28c7ad727bc42c363fa37c543fa9a428090fb4c97f0445f886b8",
  "tx": [
    "c84ec94f40f618a6fc168d0d17e869a6b81d342304212999ca81c1ebf0a17de9",

    "3aca442b1fdf9210ae2d66a530759c407d465203005d5ea7250b3dd2169511d4"
  ],
  "time": 1533339910,
  "mediantime": 1533339846,
  "nonce": 1902934454,
  "bits": "1a0f78e0",
  "difficulty": 1084331.558052198,
  "chainwork": "000000000000000000000000000000000000000000000085c1e541b4628b5cdf",
  "nTx": 205,
  "previousblockhash": "0000000000000cf58ba5dc4f8f2eba6beeb6d7fa79f8272325a4f5aae3ae58c5",
  "nextblockhash": "0000000000000d7969601e46be6a1407de6cccf72af4d4dd7b48e364801b8d0d"

上のbitcoin-cliでとってきたブロックを例にすると

  • Version

"versionHex": "20000000",

リトルインディアンなので、version2ということかな。

  • previousblockhash 前のブロックのハッシュは、

"previousblockhash": "0000000000000cf58ba5dc4f8f2eba6beeb6d7fa79f8272325a4f5aae3ae58c5",

  • マークルルート "merkleroot": "ab16d417f9dd28c7ad727bc42c363fa37c543fa9a428090fb4c97f0445f886b8",

トランザクションのマークルツリーを作ってそのハッシュを算出すると。

  • タイムスタンプ "time": 1533339910,

UNIX秒なと日2016本時間で 2018/08/04 08:45:10

  • nonce

"nonce": 1902934454,

  • difficulty "difficulty": 1084331.558052198,

difficultyは、約10分でマイニングされるようになってるのは、何回も書いてきたと思うけど、 この値をどのように調整するか分かってなかったので、調べてみた。

2016ブロックごとに更新が行われて、下の式で産出されるとのこと 新しいDifficulty = 旧Dfficulty * 2016ブロック目にかかった時間 / 20160(分) とのこと。

Satoshi Nakamotoのgenesisブロックメッセージ

ブロックチェーンgenesisブロックといわれるSaoshi Nakamotoが作った一番最初のブロックのに刻んだメッセージをプログラムでみてみましょう。 ちなみにこのgenesisブロックは、libbitocoinのソースに組み込まれているそうです。

mastering bitcoinのソースをちょっと書き換えて、libitcoinの最新バージョンに対応してみました。

#include <iostream>
#include <bitcoin/bitcoin.hpp>
using namespace bc;

int main() {

    //genesisブロックの取得
    chain::block block = chain::block::genesis_mainnet();

    //ブロックの最初のトランザクションの取得つまりcoinbaseトランザクションの取得
    chain::transaction coinbase_tx = block.transactions().at(0);
    assert(coinbase_tx.inputs().size() == 1);

    const chain::transaction::ins& coinbase_inputs = coinbase_tx.inputs();
    const chain::input coinbase_input = coinbase_inputs.at(0);

    //scriptをrawデータに変換
    const chain::script scr = coinbase_input.script();
    const data_chunk raw_message = scr.to_data(false);
    std::string message;
    message.resize(raw_message.size());
    std::copy(raw_message.begin(), raw_message.end(), message.begin());

    // genesisブロックメッセージの表示
    std::cout << message << std::endl;
    
    return 0;
}

コンパイルして実行すると...

$ ./satoshiwords
EThe Times 03/Jan/2009 Chancellor on brink of second bailout for banks

訳すと タイム紙 2009年1月3日 大臣は銀行への二度目の救済を決めようとしている

おお、これがSaoshi Nakamotoのメッセージか! 既存の通貨の脆弱な点をニュースを取り上げる照ところがおもしろい。

ここからビットコインのすべてが始まった。

トランザクションの優先度

試しにマイニングのプログラミング組みたいな~ということで、マイニング周りをマイニングっと。

トランザクションの優先度

マイニングする際、トランザクションの優先度

Priority = Sum( Value of input * Input Age)/Transaction Size

新しく小さいvalueインプット(Value of Input)をもつトランザクションよりも古くて大きいvalueインプットが優先

トランザクション年齢(Input Age)は、UTXOが含まれているブロックがブロックチェーンの何ブロック「深いか」

優先度が高いトランザクション(High Priority transaction)

優先度が高いトランザクションの定義は、下の式の優先度が57,600,000よりも大きいものだそう

High Priority > 100,000,000 satoshis * 144 blocks / 250 bytes = 57,600,000

この基準値は、 valueが1bitcoin = 1億satoshis

で、

年齢が

1日= 144ブロック (10分ごとにブロックが作られるので、60分×24時間/10分)

データサイズは、

250バイト

に相当。

ブロックのトランザクションの最初の50KBは、このHigh Priority transactionのために確保。 ここには、(古い)手数料なしのトランザクションも含む。

High Priority transactionの後は、最低トランザクション手数料を持つもので、優先度は、トランザクション手数料をトランザクションのデータサイズで割った値が高い順で埋められるっと。

ここでトランザクション手数料と優先度が関係するのね。

ともかく、そうやってトランザクションをプールしておくと。

generationトランザクション

generationトランザクション

ブロックの最初に追加されるトランザクション

マイニングの報酬(今は12.5bitcoin) + トランザクションから得られた総トランザクション手数料

をマイナーのアドレスに送るトランザクションを入れる。

インプットとしてUTXOを持たずに、Unlocking Scriptの代わりにcoinbaseとよばれるインプットをもつ。

 generationトランザクションインプットの構造

サイズ フィールド名 説明
32バイト Transaction Hash すべてのビットが0
4バイト Output Index すべてのビットが1 つまり 0xFFFFFFFF
1-9バイト Coinbase Data Size coinbase dataサイズの長さ(2~100バイト)
可変 Coinbase Data 任意のデータ。現在は実質、ブロック高から始まる各データ
4バイト Sequence Number 0xFFFFFFFFで固定

 coinbase data

任意のデータだったけど、現在は、version-2ブロックの仕様でブロック高から始まる各データをいれる。

ブロック高の他にも、extra nonce(まだわかんない。。)、P2SH対応情報などが含まれる。

マークルツリー

ちょくちょく出てきたけど、よくわからなかったマークルツリー そんなに難しいものでもないんですね。

マークルツリー

トランザクションAを2回SHA256にかける。それをHaとする。 また、トランザクションBを2回SHA256にかけたものをHbとする。

次は、Ha+Hbをハッシュにかけて、親のノードとする。 二分木になるようにそれを繰り返して、ツリーのルートまで作成する。

そのルートのハッシュ値は、ブロックヘッダにのると。

SPVノード

軽量のSPVノードは、すべてのトランザクションを持たずに、ブロックヘッダのみを持っている。

ピアから対象トランザクションに関するブロックヘッダとマークルツリーのパスを受け取る。 このマークルパスを使って対象トランザクションがブロックに含まれていることを確認。 また、ブロックヘッダを用いて、すでに保持するブロックチェーン情報と結びつける。 このことから、対象トランザクションブロックチェーンに記録されていることを確認できる。