2017.06.19

Z.com Cloud ブロックチェーンで仮想通貨を実装する ver.2


こんにちは。次世代システム研究室のT.M. です。

はじめに

本ブログでも、いくつかの記事で取り上げているように、Z.com Cloud ブロックチェーンおよびConoHa ブロックチェーンがβ版としてリリースされております。利用方法の解説として、ガイドが公開されておりますが、ガイドには、コントラクトの実装についてサンプル程度のものしかないため、実際にアプリケーションでは、どのような実装になるか、イメージがつかみにくいかもしれません。そこで、本記事では、実践的なアプリケーションの実装を行いましたので、全3回でそのコード解説およびデモンストレーションを行います。本投稿は第2回になります。第1回はこちらになります。

アプリケーション ver.1 おさらい

ver.1 では、サンプルアプリケーションとして、仮想通貨を実装しました。Z.com Cloud ブロックチェーンのスマートコントラクトの作成方法に則り、Main コントラクト、Logic コントラクト、Event コントラクトおよびTable コントラクトの4種類のコントラクトを作成しました。仮想通貨の機能として、所持金の確認および仮想通貨の移動のみを実現しました。

アプリケーション ver.2 概要

一般的にブロックチェーンは記録したデータの改ざんができないため、スマートコントラクトさえも内容を変更することができません。そのため、バグ修正や新機能の追加もすることができません。しかし、Z.com Cloud ブロックチェーンでは、コントラクトのバージョンアップが可能です。本記事では、通貨の発行機能を追加することで、Z.com Cloud ブロックチェーンのバージョンアップ方法について説明します。
バージョンアップでは、Main コントラクトは継承をして、Logic コントラクトは差分だけを新しいバージョンとし、Main コントラクトから適切なバージョンのロジックを呼び出します。クラス図は以下の通りです。
mycoin_class

スマートコントラクト

通貨の発行機能には、Main コントラクトおよびLogic コントラクトの変更が必要です。一方で記録するデータに変更がないため、Table コントラクトには修正が必要ありません。また、今回は、発行のイベントはアドレス0からの送金イベントとみなすので、Event コントラクトにも修正が必要ありません。

Main コントラクト

Main コントラクトとして、MyCoinContract_v2.sol は以下の通りであり、ポイントとなるコードを解説します。
pragma solidity ^0.4.2;

import './MyCoinContract_v1.sol';
import './MyCoinLogic_v1.sol';
import './MyCoinLogic_v2.sol';

contract MyCoinContract_v2 is MyCoinContract_v1 {
    MyCoinLogic_v2 public logic_v2;

    function MyCoinContract_v2(ContractNameService _cns, MyCoinLogic_v1 _logic1, MyCoinLogic_v2 _logic2) MyCoinContract_v1(_cns, _logic1) {
        logic_v2 = _logic2;
    }

    function setMyCoinLogic_v2(MyCoinLogic_v2 _logic2) onlyByProvider {
        logic_v2 = _logic2;
    }

    function checkTimestamp(uint _timestamp) private constant returns(bool) {
        return (now - TIMESTAMP_RANGE < _timestamp && _timestamp < now + TIMESTAMP_RANGE);
    }

    function create(bytes _sign, uint _timestamp, uint _value) {
        if (!checkTimestamp(_timestamp)) throw;
        bytes32 hash = calcEnvHash('create');
        hash = sha3(hash, _timestamp);
        hash = sha3(hash, _value);
        address sender = recoverAddress(hash, _sign);
        logic_v2.create(sender, _value);
    }
}

MyCoinContract_v1 の継承

Z.com Cloud ブロックチェーンのコントラクトでは、Main コントラクトはVersionContract を継承する必要があります。バージョンアップの際は、以前のバージョンのMain コントラクトを継承することで、新しいバージョンのMain コントラクトを作成します。これにより、VersionContract の継承も行い、かつ旧バージョンの機能も継承することができます。ただし、以前の機能を削除したい場合は、オーバーライドして無効にしたり、VersionContract を直接継承して、必要な機能をすべて記述する必要があります。

Logic コントラクトの呼び出し

Main コントラクトでは、旧バージョンを含めた適切なバージョンのロジックを呼び出します。

Logic コントラクト

Logic コントラクトとして、MyCoinLogic_v2.sol は以下の通りであり、ポイントとなるコードを解説します。
pragma solidity ^0.4.2;

import '../../gmo/contracts/VersionLogic.sol';
import '../../gmo/contracts/AddressGroup_v1.sol';
import './MyCoinAccountTable_v1.sol';
import './MyCoinEvent_v1.sol';

contract MyCoinLogic_v2 is VersionLogic {
    MyCoinAccountTable_v1 public myCoinTable_v1;
    MyCoinEvent_v1 public event_v1;
    address public admin;

    modifier onlyFromAdmin(address _sender) {
        if (_sender != admin) throw;
        _;
    }

    function MyCoinLogic_v2(ContractNameService _cns, MyCoinAccountTable_v1 _myCoinTable, MyCoinEvent_v1 _event, address _admin) VersionLogic(_cns, 'MyCoin') {
        myCoinTable_v1 = _myCoinTable;
        event_v1 = _event;
        admin = _admin;
    }

    function exist(address _account) constant returns (bool) {
        return myCoinTable_v1.exist(bytes32(_account));
    }

    function create(address _sender, uint _value) onlyByVersionContractOrLogic onlyFromAdmin(_sender) {
        if (!exist(_sender)) myCoinTable_v1.create(_sender);
        myCoinTable_v1.setAmount(_sender, getAmount(_sender) + _value);
        event_v1.send(0, _sender, _value);
    }

    function getAmount(address _account) constant returns (uint) {
        return myCoinTable_v1.getAmount(_account);
    }
}

VersionLogic の継承

Logic コントラクトでは、Main コントラクトとは異なり旧バージョンのLogic コントラクトを継承しません。なぜなら、Main コントラクトが必要に応じて、それぞれのバージョンのLogic コントラクトを呼び出すからです。その結果、新バージョンのLogic コントラクトでは、新機能のみを実装すれば良いです。

Web アプリケーション

上記で実装したMyCoin に対して、Web アプリケーションとして利用する方法を解説します。ここでは、上記コントラクトがデプロイされているものとします。

ABI の変更

Main コントラクトが変更されたため、ABI を変更する必要があります。変更箇所は、管理画面およびクライアントアプリです。

デモンストレーション

実装したアプリケーションのデモンストレーションを行います。

通貨発行

通貨を発行することのできるアカウントのアドレスを0xfc865f061f183129985e9224a52293a95bb1f916、一般ユーザのアカウントのアドレスを0xadd1c664db02f7fcb898ed6cbb1fc63635c11a1d とする。通貨発行アカウントが1111 だけ通貨を発行することで、所持金が増加します。
coin-admin-info coin-admin-info

権限のないユーザの発行禁止

一般ユーザが通貨を発行します。その際は、エラーが出て失敗します。
coin-admin-info

送金処理

旧バージョンの機能であった、送金処理も可能です。
coin-admin-info coin-admin-info
送金元の所持金が減ります。

coin-admin-info coin-admin-info
送金先の所持金が増えます。



さいごに

Z.com Cloud ブロックチェーンの特長である、コントラクトのバージョンアップを行うことで、コントラクトに新機能を追加しました。一般的なプログラムにおけるバージョンアップとは異なるため、理解しづらいかもしれません。この記事が理解の助けになればと思います。

次回予告

Z.com Cloud ブロックチェーンには、データをアクセスコントロールして管理する、というものがあります。次回はそれを利用して、さらに追加の機能を実装します。

次世代システム研究室では、グループ全体のインテグレーションを支援してくれるアーキテクトを募集しています。インフラ設計、構築経験者の方、次世代システム研究室にご興味を持って頂ける方がいらっしゃいましたら、ぜひ 募集職種一覧 からご応募をお願いします。

皆さんのご応募をお待ちしています。