最近yarnにはまりまくって抜け出せず。トレードでは沼にはまっているsyroheiです。Ethereum界隈ではハードフォークに次ぐハードフォークでインフラレイヤーのバグが多く、なかなかEthereumの開発が進まない状態ですが。Ðappの開発状況は着々と前に進んでいるので紹介していきます。
前回に引き続きtruffleを使った ②爆速で銀行を設立する です。
前回の記事の続きです => サーバーレスフレームワークTruffleでÐappを爆速開発する ①truffle tutorial
まえおき
truffleとは
TruffleはConsensysが開発したパブリック・プライベートEthereumのSmartContract開発フレームワークです。
フロントエンド開発からMainNet Deployまでスムーズに開発できるのが特徴です。2016年4月に正式リリースされました。
https://github.com/ConsenSys/truffle
Ðappとは
ÐappはDecentralized Appliction の略で非中央集権型実行環境Ethereum Virtual Machine(EVM)上で走るスマートコントラクトで実現できるアプリケーションのこと。ダップス or ディアップスと呼ぶらしい
- サーバーレス志向(サーバーが世界中に分散しており、すべてが無料(マイニングや寄付)で運営されている、SPFがほとんどない)。
- アプリケーションのデプロイと実行にはgas(Ethereum , Ethereum Classic)が必要。
Distributed View Controller Model
- DVCは世界中に分散されたEthereumをMVCのmodelに当てはめたアーキテクチャモデル。
- これにより信頼が必要なデータロジックをblockchainに格納しblackbox化が行える。そのため金融面で必要なセキュリティをdistributed側で担保つつ、controllerとviewはUI/UXに専念できる。
目的
スタートアップやベンチャー企業が素早く銀行サービスをスタートする時に限られたリソースで銀行システムを作るには、非常に大きなインフラコストがかかります。クラウドベースのマネジードサービスでは攻撃アクセス量が増大しその分セキュリティ対策費用が膨大になってしまう問題がありました。Ethereumベースのサービスアプローチでこのインフラコストをほとんどゼロにをすることが目的です。
Ethereum network上でサービスロジックを実行することにより、バックエンドコストをほとんどゼロに抑えならがら、開発者は安全に金融ビジネスのロジックをあらゆるアプリケーションに組み込むことが可能になります。開発者が耐障害性やを考えなくても設計できるため、開発者はフロントエンドの開発を集中して行うことが出来るため生産性の向上が期待できます。これにより開発チームはより自由にユーザ体験を設計する時間を増やすことができるでしょう。
それでは早速作っていきましょう。まずはコントラクトのロジックと実装から
爆速で銀行を作るために必要最低限のロジック
- ユーザの登録、削除、属性変更
- 資産の保管、凍結、送受信、貸付金と預金の管理
1.ユーザの管理
銀行はユーザの預金を預かるため、ユーザはユーザの残高にアクセスするためにはアイデンティティの証明が必要となります。アイデンティティの証明は二つのシンプルなロジックからなります。
- owner認証による電子署名つきのユーザ登録トランザクション
- ユーザの電子署名つきの実行命令メッセージングトランザクション
ここで言うownerとは事業主の管理者のethereumアドレスです
これらのトランザクションはSolidityで以下のように記述できます
pragma solidity ^0.4.0;
library Validate {
// We define a new struct datatype that will be used to
// hold its data in the calling contract.
struct Data { mapping(address => bool) map; }
// Note that the first parameter is of type "storage
// reference" and thus only its storage address and not
// its contents is passed as part of the call. This is a
// special feature of library functions. It is idiomatic
// to call the first parameter 'self', if the function can
// be seen as a method of that object.
function insert(Data storage self, address value)
returns (bool)
{
if (self.map[value])
return false; // already there
self.map[value] = true;
return true;
}
function remove(Data storage self, address value)
returns (bool)
{
if (!self.map[value])
return false; // not there
self.map[value] = false;
return true;
}
function show(Data storage self, address value)
returns (bool)
{
if (self.map[value] != true)
return false;
return true;
}
}
2.資産の保管、凍結、送受信、貸付金と預金の管理
銀行は通常お客様の資産を運用しています。それらは預金であり、業務によって残高を変更、保管、凍結する必要があります。
pragma solidity ^0.4.2;
// This is just a simple example of a coin-like contract.
// It is not standards compatible and cannot be expected to talk to other
// coin/token contracts. If you want to create a standards-compliant
// token, see: https://github.com/ConsenSys/Tokens. Cheers!
import "Validate.sol";
contract owned {
function owned() {}
address owner;
modifier onlyOwner {
if (msg.sender != owner)
throw;
_;
}
}
contract User is owned{
mapping (address => uint) balances;
mapping (address => uint) lending_balances;
Validate.Data validated_user;
Validate.Data locked_user;
function User(address _owner ){
owner = _owner;
}
function register(address _user) onlyOwner {
if (!Validate.insert(validated_user, _user))
throw;
}
function remove(address _user) onlyOwner {
if (!onlyUser(_user))
throw;
if (!Validate.remove(validated_user, _user))
throw;
}
function account_lock(address _user) onlyOwner {
if (!onlyUser(_user) || !lockable(_user))
throw;
if (!Validate.insert(locked_user, _user))
throw;
}
function send(address _receiver, uint _amount) onlyUser returns(bool sufficient) {
if (!onlyUser(msg.sender) || !onlyUser(_receiver) || !lockable(msg.sender) )
return false;
if (balances[msg.sender] < _amount)
return false;
balances[msg.sender] -= _amount;
balances[_receiver] += _amount;
return true;
}
function getBalanceOfGeneral(address addr) returns(uint) {
return balances[addr];
}
function getBalanceOfLending(address addr) returns(uint) {
return lending_balances[addr];
}
function onlyUser(address _user){
return Validate.show(validated_user, _user);
}
function lockable(address _user){
return Validate.show(locked_user, _user);
}
}
これらのContractはEthereum network上でデプロイされ、関連付けされます。各ContractはデプロイされるとユニークなaddressとContract ABIを持ち、アクセス可能になります。UserContractはValidateContractを参照可能であり、ライブラリとして利用しています。
作り方
1. dockerを入れる
2. docker-composeを入れる
3. yarnを入れる
npm install -g yarn
4. ether-bankをcloneしてyarn install
$ git clone https://github.com/syrohei/ether-bank
$ cd ether-bank
$ yarn install -g
5. gethを起動
$ docker-compose up -d
6. testrpc でcontract をテスト
$ testrpc -b
$ truffle test
自動的にsolcが呼ばれてコンパイルされ、testrpcにデプロイされてテストされます。
7. Contractをデプロイ
$ truffle migrate --network mainnet
$ truffle networks
truffle migrate option
truffleのいいところは--network
オプションで各ネットワーク(private, public, test-rpc)のデプロイメントターゲットを指定できるので、バージョンが異なるapplicationを手軽に管理することが容易です。また、デプロイされたコントラクトを一覧表示するtruffle network
も非常に強力です。
$ truffle migrate --network testnet //deploy target = testnet eth
コードはこちら
https://github.com/syrohei/ether-bank
まとめ
第二回目では銀行業務のコントラクトを実装してみました。Solidityの印象はオブジェクト指向というよりは関数型の志向が強いと感じられるにもかかわらずJavascriptライクな言語仕様なので書いていてあまり心地よい感じはしないので中途半端な感じになります。
Ethereum系のプロダクトは分散型を目指しているにもかかわらず、管理者が存在するという矛盾が多くのプロジェクトに見て取れるため、フィージビリティが非常に苦しい状態となっています。そもそもワールドコンピュータなので特定のニーズに特化した処理は管理者や演算命令の主体が必要なので、分散型で行うメリットがないと思われます。しかしならがらより普遍的な処理(投票トリガーや着金トリガー、送受金や信用証明等)の拡張を行うことが可能であるならば完全な分散型になるための要素実装が着実に動きだすと思います。現在コアデブ達はwhisperプロトコルの実装とモバイル向けの軽量ノードの開発を行っておりそちらも期待しています。また来年の1Qに登場すると思われる期待のメジャーアップデートEthereum Metropolisも大きなハードフォークになりそうなので色々楽しみです笑