Bitcoinベースで独自ブロックチェーンネットワークを構築する Part 1


はじめに

今回から複数回に渡って、Elementsを使った独自ブロックチェーンの構築方法を紹介していきます。
Elementsとは、2016年6月に公開されたBitcoinのコードベース上に構築されたオープンソースのブロックチェーンプラットフォームです。

Elements 公式
Elements github repository

特徴としては以下のようなものがあります。


Bitcoin コードベース

Bitcoinのコードベース上に構築されており、ブロックチェーン部分に関してはBitcoinと同等の安全性を確保できます。また、コミュニティメンバーによりBitcoinの最新版のコードベースを常に取り込んでいるため、新しく実装された機能もすぐに利用できます。

アセット発行

独自アセットを発行する機能がネイティブで実装されているため、スマートコントラクトを書くこと無くRPCで作成できます。

Signed Blocks

署名によってブロックを生成することが出来ます。署名は複数の秘密鍵による署名にも対応しており、これにより分散型の特性を維持しつつ、ブロックの検証時間を短縮し、ブロックチェーンの分岐・再編成を防ぐことができます。

サイドチェーン機能

既存のブロックチェーン(ビットコインなど)に「ペグ」することで、Elementsで構築したブロックチェーンとの双方向のアセット移動が可能になります。

コンフィデンシャル トランザクション

コンフィデンシャル トランザクションを使うと、送信されたアセットの数量がブロックチェーン上では秘匿化されプライバシーを保護することが出来ます。また、秘匿化された情報は、アセットの送受信をしている当事者のみが閲覧できます。

Elementsを使うとBitcoinと同等の安全性を持った独自ブロックチェーンネットワークや、Bitcoinのサイドチェーンネットワークを構築することが出来ます。

Elementsをベースにしたサイドチェーンが実際に使用されている例として、Blockstream社のLiquidがあります。

構築手順

1. elementsのdocker imageのビルド

今回使用するファイルをgithub repositoryから取得します。

git clone https://github.com/cryptogarageinc/build-original-blockchain-network-with-elements.git

プロジェクトフォルダへ移動します。

cd ./build-original-blockchain-network-with-elements/part-1

docker imageをビルドします。今回は elements というタグを付けることにします。

docker build -t elements .

2. elementsの起動

docker run --rm --name elements -d elements

ブロックの情報を確認してみます。

docker exec -it elements elements-cli getblockchaininfo

以下のような情報が表示されます。

{
  "chain": "liquidregtest",
  "blocks": 0,
  "headers": 0,
  "bestblockhash": "00902a6b70c2ca83b5d9c815d96a0e2f4202179316970d14ea1847dae5b1ca21",
  "mediantime": 1296688602,
  "verificationprogress": 0,
  "initialblockdownload": true,
  "size_on_disk": 397,
  "pruned": false,
  "signblock_asm": "1",
  "signblock_hex": "51",
  "current_params_root": "3700bdb2975ff8e0dadaaba2b33857b0ca2610c950a92b1db725025e3647a8e1",
  "current_signblock_asm": "0 4ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260",
  "current_signblock_hex": "00204ae81572f06e1b88fd5ced7a1a000945432e83e1551e6f721ee9c00b8cc33260",
  "max_block_witness": 74,
  "extension_space": [
    "02fcba7ecf41bc7e1be4ee122d9d22e3333671eb0a3a87b5cdf099d59874e1940f02fcba7ecf41bc7e1be4ee122d9d
22e3333671eb0a3a87b5cdf099d59874e1940f"
  ],
  "epoch_length": 10,
  "total_valid_epochs": 2,
  "epoch_age": 0,
  "softforks": [
    {
      "id": "bip34",
      "version": 2,
      "reject": {
        "status": true
      }
    },
    {
      "id": "bip66",
      "version": 3,
      "reject": {
        "status": true
      }
    },
    {
      "id": "bip65",
      "version": 4,
      "reject": {
        "status": true
      }
    }
  ],
  "bip9_softforks": {
    "csv": {
      "status": "active",
      "startTime": -1,
      "timeout": 9223372036854775807,
      "since": 0
    },
    "segwit": {
      "status": "active",
      "startTime": -1,
      "timeout": 9223372036854775807,
      "since": 0
    },
    "dynafed": {
      "status": "active",
      "startTime": -1,
      "timeout": 9223372036854775807,
      "since": 0
    }
  },
  "warnings": ""
}

"chain"の値が"liquidregtest"になっています。これは、elementsがregression test modeで起動している事を示しています。"blocks"が現在のブロック高になります。初回起動時ではまだブロックが生成されていないので“0”となっています。

3. ブロックの生成

まずはアドレスを作成します。

addr=$(docker exec -it elements elements-cli -rpcwallet=alice getnewaddress)

ブロックを生成します。第1引数が生成するブロックの数になります。先程、作成したアドレスは生成するブロックのcoin baseに使用されます。

docker exec -it elements elements-cli generatetoaddress 1 ${addr}

ブロックの生成に成功すると以下のような32バイトの hash が表示されます。

[
  "1c09df9b5d78f4692ae5bd8fab0985bd1369d31582adb5738a147d7a5418d031"
]

生成されたブロックを確認してみます。

docker exec -it elements elements-cli getblockchaininfo

“block”が 1 と表示されブロックが高が一つ増えたことが確認できます。

{
  "chain": "liquidregtest",
  "blocks": 1,
  "headers": 1,
  "bestblockhash": "1c09df9b5d78f4692ae5bd8fab0985bd1369d31582adb5738a147d7a5418d031",
  "mediantime": 1615987355,
[ 以下、省略 ]

4. アセットの送金

今回は、”alice”と”bob”という名前でwalletを2つ用意しています。また、初回使用者が自由に使える21000000 BTCを初期段階で発行しています。

まずは、aliceの残高を確認してみます。

docker exec -it elements elements-cli -rpcwallet=alice getbalance

aliceの残高は21000000 BTCです。

{
  "bitcoin": 21000000.00000000
}

次に、”bob” の残高を確認してみます。

docker exec -it elements elements-cli -rpcwallet=bob getbalance

bobの残高も21000000 BTCとなっており、この時点では、aliceもbobも21000000 BTCを保有しているように見えます。

{
  "bitcoin": 21000000.00000000
}

では、aliceからbobへ送金してみます。
bobのアドレスを取得します。

$ addr_bob=$(docker exec -it elements elements-cli -rpcwallet=bob getnewaddress)

aliceのウォレットからbobへ送金してみます。第1引数が送金するBTCの数、第2引数が送金先アドレス(今回は上記で取得したbobのアドレス)になります。

docker exec -it elements elements-cli -rpcwallet=alice sendtoaddress 5 ${addr_bob}

トランザクションのブロードキャストが成功するとトランザクションID(32bytesのhash)が表示されます。下記は、トランザクションIDの一例です。

3bde425df558dc7521cc4add6e8ee7b2ad148b55599faaf04c64590b8a447b4b

この時点では、トランザクションがelements nodeに受け付けられただけで、ブロックには取り込まれていません。

ブロックを生成してトランザクションをブロックチェーンへ記録してみます。

docker exec -it elements elements-cli generatetoaddress 1 ${addr}

bobのbitcoinが増えていることを確認してみます。

docker exec -it elements elements-cli -rpcwallet=bob getbalance

5 BTCが残高として認識されていることが確認できます。

{
  "bitcoin": 5.00000000
}

aliceのwallet残高を確認してみます。

docker exec -it elements elements-cli -rpcwallet=alice getbalance

5 BTCとfeeとして支払った分のBTCが減少していることが確認できます。

{
  "bitcoin": 20999994.99995068
}

まとめ

今回は docker を使って elements を起動し2者間で送金するところまでを紹介しました。次回は、複数の elements でネットワークを構築する手順を紹介していきます。

今回使用したソースコードはこちらの Crypto Garageのリポジトリ で公開されています。