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

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

[Elements 公式](https://elementsproject.org/)
[Elements github repository](https://github.com/ElementsProject/elements)

特徴としては以下のようなものがあります。
<dl>
<dt>Bitcoin コードベース<dt>
<dd>Bitcoinのコードベース上に構築されており、ブロックチェーン部分に関してはBitcoinと同等の安全性を確保できます。また、コミュニティメンバーによりBitcoinの最新版のコードベースを常に取り込んでいるため、新しく実装された機能もすぐに利用できます。</dd>
<dt>アセット発行</dt>
<dd>独自アセットを発行する機能がネイティブで実装されているため、スマートコントラクトを書くこと無くRPCで作成できます。</dd>
<dt>Signed Blocks</dt>
<dd>署名によってブロックを生成することが出来ます。署名は複数の秘密鍵による署名にも対応しており、これにより分散型の特性を維持しつつ、ブロックの検証時間を短縮し、ブロックチェーンの分岐・再編成を防ぐことができます。</dd>
<dt>サイドチェーン機能</dt>
<dd>既存のブロックチェーン（ビットコインなど）に「ペグ」することで、Elementsで構築したブロックチェーンとの双方向のアセット移動が可能になります。</dd>
<dt>コンフィデンシャル　トランザクション</dt>
<dd>コンフィデンシャル　トランザクションを使うと、送信されたアセットの数量がブロックチェーン上では秘匿化されプライバシーを保護することが出来ます。また、秘匿化された情報は、アセットの送受信をしている当事者のみが閲覧できます。</dd>
</dl>

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

Elementsをベースにしたサイドチェーンが実際に使用されている例として、Blockstream社の[Liquid](https://blockstream.com/liquid/ "Liquid Network")があります。

# 構築手順
### 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)
```
ブロックを生成します。第１引数が生成するブロックの数になります。先程、作成したアドレスは生成するブロックのcoin baseに使用されます。

```
docker exec -it elements elements-cli generatetoaddress 1 ${addr}
```
ブロックの生成に成功すると以下のような３２バイトの 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を２つ用意しています。また、初回使用者が自由に使える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へ送金してみます。第１引数が送金するBTCの数、第２引数が送金先アドレス（今回は上記で取得した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のリポジトリ](https://github.com/cryptogarageinc/build-original-blockchain-network-with-elements) で公開されています。