bitFlyer BlockchainのDevメンバーがブロックチェーンや日々の開発について投稿します。

miyabiブロックチェーンでの簡単な.NETアプリの作り方(パート1)

bitFlyer BlockchainのResearch Teamです。 本短編シリーズでは、実際のアプリケーションで miyabi を利用する方法を一つ一つ順を追ってご紹介します。 (本ブログは、bitFlyer Blockchainのエンジニア Thomasの英語ブログを日本語に翻訳したものです。)

本シリーズの目標は、開発者に miyabi 上でのアプリケーション制作方法を教授することです。本シリーズの各チュートリアルでは、ブロックチェーン技術で解決可能な具体的な問題が提示されます。その後に解決策と実装の詳細な説明が示されます。本シリーズを通してあなたが miyabi での作業を楽しく経験し、将来のアプリケーションで miyabi の使用を検討されることを願っています。

パート1では、miyabi 上での簡単なウォレットの作り方を説明します。

前提条件

・ブロックチェーンの暗号に対する基本的な理解

miyabi マニュアル(AssetTable)の読了

簡単な定義

miyabi ― miyabi は、bitFlyer Blockchain が独自に開発したブロックチェーンです。高いトランザクション能力を特徴とし、一般的なアプリケーションでブロックチェーンを実用化する目的で開発されました。またデータの操作やクエリのための強力なツールを提供します。

テーブル ― テーブルは、ブロックチェーン内に格納した論理的なまとまりのあるデータ集合のことです。テーブルには型(タイプ)があり、タイプごとに、独自のビュー(データのまとめ方)と、テーブルに対して実行可能な一組の操作が定められます。

ウォレット ― ウォレットは、デジタル資産を管理するソフトウェアです。公開鍵と秘密鍵を処理し、ユーザーは資産の保管や引き出しができます。

シナリオ

アリスはケーキショップのオーナーです。リワードプログラムを導入して、顧客ロイヤルティーの確立と顧客維持率アップを通じて事業を活性化したいと考えています。このプログラムでは、購入総額のパーセンテージに応じて各顧客に「CookiePoint」というトークンを発行したいと考えています。CookiePoint は顧客どうしで自由に移転でき、アリスのお店で景品と交換することもできます。アリスはこの経済圏の中央銀行として望むだけの CookiePoint を生成できます。ただし、アリスは顧客にトークンの完全な所有権と、交換の自由を与えたいと考えています。こうした理由から、アリスはバックエンドシステムに miyabi ブロックチェーンを利用することにしました。miyabi ブロックチェーンでは、トランザクション送信のための追加のコストの心配なしに、将来の事業拡張にも耐えられる十分な処理速度とブロックチェーンのメリットを享受できます。

Asset モジュールから始める

Asset モジュールを使って、miyabi 内にAsset Table を作成できます。このテーブルは<アドレス, 残高> のペアという形式で情報を扱います。

また Asset Table は以下の操作をサポートします。

  • AssetGen: あるアドレスの残高を指定した額だけ増やします。テーブル所有者だけがこの操作を実行できます。

  • AssetMove: 送信元アドレスの残高を指定した額だけ減らし、同時に、受信者アドレスの残高を同じ額だけ増やします。トランザクションは送信元アドレスの秘密鍵で署名する必要があります。

モジュールを利用するためには、最初に以下のメソッドを呼び出して、このモジュールのすべてのシリアライズ化オブジェクトタイプコードをレジストリーに登録する必要があります。

AssetTypesRegisterer.RegisterTypes(); 

トランザクションを miyabi に向けてブロードキャストするために以下のようにシングルトンクラスを作成します。

var client = new Client(SdkConfig.Load(SDK_CONFIG_PATH));
var _generalClient = new GeneralApi(client);
ステップ1:Asset Table の作成

Asset Table の作成時にはいくつかのパラメーターが必要です。

  • テーブル名: ユニークなテーブル識別子です。今回はトークンの名前をテーブル名に使用します。つまり「CookiePoint」です。

  • テーブル所有者: これはトークン発行など制限付き操作の実行権限を有する公開鍵(アドレス)になります。ここではアリスの公開鍵を用います。

var alicePubKey = PublicKey.Parse(ALICE_PUBLIC_KEY_ADDRESS);
var aliceAddress= new PublicKeyAddress(alicePubKey);
var assetTable = new CreateTable(new AssetTableDescriptor(
    "CookiePoint", false, false, new []{aliceAddress}));

このトランザクションは「TableAdmin」権限を有する秘密鍵で署名する必要があります。

注:TableAdmin 権限とTableOwner 権限。前者はテーブルの作成・削除を可能にし、後者は自身が所有するテーブルに関する特殊な操作(資産の生成)を可能にします。

トランザクションにメモを加えてみましょう。

var memo = new MemoEntry(new []{"Point system for Alice's shops"});

var tx = TransactionCreator.SimpleSignedTransaction(
    new ITransactionEntry[]{assetTable, memo},
    new []{PrivateKey.Parse(TABLE_ADMIN_PRIVATE_KEY)});

最後に、トランザクションをmiyabiに送信します。

async Task SendTransaction(Transaction tx)
{
    try
    {
        var send = await _generalClient.SendTransactionAsync(tx);
        var result_code = send.Value;

        if (result_code != TransactionResultCode.Success
            && result_code != TransactionResultCode.Pending)
        {
            //Transaction rejected, log result_code.
        }
    }
    catch (Exception e)
    {
        //Log error.
    }
}
ステップ2:資産の発行

アリスの公開鍵アドレスをテーブル所有者として、テーブルが作成されました。アリスは自身の秘密鍵を用いて、任意のアドレスに資産を生成できます。今、アリスは顧客配布用に自身に1,000,000ポイント生成したいと考えているとしましょう。

var generateAsset = new AssetGen("CookiePoint", 1000000m, aliceAddress);

今回は、アリス(テーブル所有者)の秘密鍵を用いてトランザクションに署名する必要があります。

var tx = TransactionCreator.SimpleSignedTransaction(
    new ITransactionEntry[]{generateAsset},
    new []{PrivateKey.Parse(ALICE_PRIVATE_KEY))});

前回同様にトランザクションをブロードキャストします。

SendTransaction(tx);
ステップ3:ウォレットの作成

アリスは、ポイント管理のためのウォレットを顧客に作成する必要があります。ウォレットはユーザーの公開鍵/秘密鍵を管理し、所有者の残高総額を記録するもので、かつ他の人にポイントを送信できないといけません。これにはアリスの店でのアリスへの送信も含まれます。

ウォレットのインターフェースを次のように定義します。

public interface IWalletService
{   
    Address GetAddress();
    Task Send(decimal amount, Address to);
    Task<decimal> GetBalance();
}

miyabi では、鍵ペア生成用にいくつかの暗号パッケージを提供しています。通常は、ビットコインと同じ楕円曲線である SECP256k1 を使用します。

private ICryptographicService _cryptographicService;

WalletService()
{
    _cryptographicService = new Secp256k1EccService();
}

暗号サービスは、鍵生成や署名などの機能を、その背後で行われる一切の複雑性を感じさせることなく、アプリケーションから簡単に使用できるようにします。トランザクションに署名するために、KeyPairはウォレットサービス内に保管する必要があります。

private ICryptographicService _cryptographicService;
private KeyPair _keyPair;

WalletService()
{
    _cryptographicService = new Secp256k1EccService();
    var privateKey = _cryptographicService.CreatePrivateKey();
    _keyPair = new KeyPair(privateKey);
}

KeyPairからアドレスを取得するのはとても簡単です。

public Address GetAddress()
{
    return new PublicKeyAddress(_keyPair.PublicKey);
}

コインを送るには、予め生成されたウォレットの秘密鍵で署名して、「AssetMove」というトランザクションを miyabi にブロードキャストする必要があります。

public async Task Send(decimal amount, Address to)
{
    var from = GetAddress();
    var moveCoin = new AssetMove("CookiePoint", amount, from, to);
    var tx = TransactionCreator.SimpleSignedTransaction(
        new ITransactionEntry[] {moveCoin},
        new PrivateKey[] {_keyPair.PrivateKey});
    await SendTransaction(tx);
}

AssetClientは、Asset Table からのハイレベルの読み出し操作を提供します。GeneralApi クライアントの場合と同様にインスタンス化する必要があります。

var client = new Client(SdkConfig.Load(SDK_CONFIG_PATH));
var _assetClient = new AssetClient(client);

WalletService 側には以下のメソッドを実装します。

public async Task<decimal> GetBalance()
{            
    var myAddress = GetAddress();
    var result = await _assetClient.GetAssetAsync("CookiePoint", myAddress);
    return result.Value;
}
ステップ4:WalletServiceのアリス決済システムへの統合

アリスは、顧客が購入に際しトークンを発行します。ウォレットを持っている顧客は、自分のアドレスを(例えば、QRコードで)アリスに提示して、トークンを受け取ることができます。逆に、顧客が自分のポイントを消費してアリスに送り返し、景品と引き換えることもできます。

次回

パート1では、Asset モジュールと暗号パッケージ、そしてごくわずかなコードを用いて、miyabi 上で暗号通貨を管理するサンプルウォレットサービスの構築方法を学びました。

次のパートでは、エンティティテーブルで miyabi 上の複雑なデータ構造を利用する方法と、それを用いてクラシファイド広告プラットフォームを構築する方法をご説明します。

ーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーーー

bitFlyer Blockchainではブロックチェーンエンジニアを絶賛採用中です!!

エンジニアチームはメンバー間のコミュニケーションを英語で行うなど様々な国籍のメンバーで構成されるチームでお互いに協力をしながら、個々人が自発的に情熱をもって仕事に取り組んでいます。 ご興味ある方は、ぜひご連絡ください!! www.wantedly.com

bitFlyer Blockchainがブロックチェーンエンジニアを募集!