libwally-coreを使ってみる

# libwally-core とは？

libwally-coreは、Blockstream社が運営する、Bitcoin サイドチェーン用プロジェクトの一つ「Wally」のライブラリ・コアです。クロスプラットフォームに対応しており、C言語、Java、Python、node-js等で利用できます。Wallyでは便利なライブラリ関数が用意されており、Blockstream社が提供するBitcoinサイドチェーン「Liquid」の開発に便利です。

libwally-core - github
https://github.com/ElementsProject/libwally-core
Elements by Blockstream
https://elementsproject.org/
Liquid
https://blockstream.com/liquid/

# C言語で使ってみよう

ではさっそく使ってみましょう。Ubuntu18.4で試してみます。
まずはgithubからcloneします。

```console:コンソール
$ git clone https://github.com/ElementsProject/libwally-core.git
$ cd libwally-core
```

次に、C言語用ライブラリを生成します。

```console:コンソール
$ ./tools/autogen.sh
$ ./configure --enable-debug
$ make
```
　これで、libwally-core/src/.libs/の位置に、libwallycore.soが生成されました。
　リンクすれば、C言語で使えます。

では、実際に動かしてみましょう。
下記サンプルで、wally_base58_from_bytes()を使ってみます。

```c:test01.c
#include <stdio.h>
#include <wally_core.h>

void main() {
    int result;
    char *output;
    const unsigned char array[] = { 0x64, 0x06, 0x02 };
    printf("wally_init: result=%d\n", wally_init(0));
    result = wally_base58_from_bytes(array, 3, 0, &output);
    printf("wally_base58_from_bytes:result=%d, output=%s\n", result, output);
    wally_free_string(output);
}
```

では、コンパイル・実行してみましょう。

```console
$ gcc -Iinclude -o test01 test01.c src/.libs/libwallycore.so
$ LD_LIBRARY_PATH=src/.libs ./test01
wally_init: result=0
wally_base58_from_bytes:result=0, output=abcd
$ 
```
　入力：0x64 0x06 0x02
　出力：abcd
上記の様に、BASE58エンコードが出来ました。

次は、HDウォレット等で使用するニーモニックを生成してみます。
ちなみに下記ソースの元ネタは、[StackOverflow](https://stackoverflow.com/questions/13205865/gcc-file-not-recognized-file-format-not-recognized)です。

```c:test02.c
#include <stdio.h>
#include <wally_bip39.h>

int main()
{
    /* Note that this array is 34 elements long which seems incorrect, it should be 32 */
    const unsigned char myArray[] = { 0x00, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22, 0x11, 0x22,  0x33 };
    char *mnemonic_secret;

    int ret = bip39_mnemonic_from_bytes(0, myArray, 32, &mnemonic_secret);
    if (ret != WALLY_OK) {
        printf("mnemonic did not work. error: %d",ret);
        return 1;
    }
    printf("HSM: your should remember / write down the following words do recover your funds!\n");
    printf("%s\n", mnemonic_secret);
    wally_free_string(mnemonic_secret);
    return 0;
}
```

こちらもコンパイル・実行してみます。

```console
$ gcc -Iinclude -o test02 test02.c src/.libs/libwallycore.so
$ LD_LIBRARY_PATH=src/.libs ./test02
HSM: your should remember / write down the following words do recover your funds!
abandon math lounge during banana ancient marriage cattle bachelor awesome embrace car canal much duty drama capital math lounge during banana ancient marriage champion
```

# node.jsで使ってみよう
次はnode.jsで使ってみましょう。
オプション「--enable-js-wrappers」を加えて、再度makeします。

```console
$ ./tools/cleanup.sh
$ ./tools/autogen.sh
$ ./configure --enable-debug --enable-js-wrappers
$ make
```
　実行すると、libwallycore/src/wrap_jsに「wally.js」が生成され、node.jsでlibwally-coreが使える様になります。

node.jsでは、サンプル「example.js」が用意されています。

```javascript:example.js
const wally = require('./wally');

wally.wally_sha256(Buffer.from('test', 'ascii')).then(function(uint8Array) {
  console.log(Buffer.from(uint8Array).toString('hex'))
});
wally.wally_base58_from_bytes(Buffer.from('xyz', 'ascii'), 0).then(function(s) {
  console.log(s);
  wally.wally_base58_to_bytes(s, 0).then(function(bytes_) {
    console.log(Buffer.from(bytes_).toString('ascii'));
  });
});

const seed = Buffer.from('00000000000000000000000000000000', 'hex');
wally.bip32_key_from_seed(seed, wally.BIP32_VER_MAIN_PRIVATE, 0).then(function(s) {
  wally.wally_base58_from_bytes(s, 1).then(function (s) {
    console.log('privkey:', s);
  });
  wally.bip32_pubkey_from_parent(s, 1, 0).then(function (pub) {
    wally.wally_base58_from_bytes(pub,  wally.BASE58_FLAG_CHECKSUM).then(function (s) {
      console.log('pubkey:', s);
    });
  });
});
```

では、実行してみましょう。

```
$ node example.js
9f86d081884c7d659a2feaa0c55ad015a3bf4f1b2b0b822cd15d6c15b0f00a08
hU2u
xyz
privkey: xprv9s21ZrQH143K2JbpEjGU94NcdKSASB7LuXvJCTsxuENcGN1nVG7QjMnBZ6zZNcJaiJogsRaLaYFFjs48qt4Fg7y1GnmrchQt1zFNu6QVnta
pubkey: xpub683nVy7Tt7baCKuqho7X5C7TGuskZAa4wQ5YEue2BxtYB6upN4YgWTyZYnLg56XDFt7YN3DrFZEYmEhMqpsZmiP73NNrR5P8WcbfWgfQGGi
$
```
　このサンプルでは、以下のAPIが使われています。
　　wally_sha256
　　wally_base58_from_bytes
　　wally_base58_to_bytes
　　bip32_key_from_seed
　　bip32_pubkey_from_parent

# おしまい

EthereumではOpenZeppelinを使う様に、Liquidサイドチェーンを扱うウォレットアプリ等を開発する際は、Blockstreamのライブラリを使うのが安心・確実だと思います。