Internet Computer Dapp開発入門

Internet Computer (IC) とは

興味のない人向けに説明するとInternet ComputerはスマートコントラクトでDappを開発できるブロックチェーンです。

Dappはいわゆる分散型アプリケーションのことで、ブロックチェーンと連携するWebアプリケーションのことです。

自分も名前は知っていたものの有象無象の1つでしょぐらいの認識だったので今回ドキュメントを通して読んでみました。

internetcomputer.org

Internet Computerの特徴

Internet ComputerはフロントエンドをSPAとして、バックエンドとデータ層をスマートコントラクトとして、フルスタックのWebアプリケーションをデプロイ可能です。

つまり新手のPaaSとして使えます。

厳密にはAsset Canisterという仕組みでフロントエンドも静的ファイル入りのスマートコントラクトとしてデプロイされていて、呼び出しに応じてHTTPのリクエスト/レスポンスを介在するBoundary nodesというエッジが居るようです。

これらのアーキテクチャがWasmを中心に構成されているのが興味深い点です。 「Swiftがこの先生きのこるには」などで話題にしたように「未来のサーバーレスへのデプロイはWasmが中心になるのでは」という夢を描いている人にもおすすめ*1

利用事例

DSCVR (分散型 Reddit)Distrikt (分散型 Twitter) そしてGmail代替のDmailなどがICによってホストされているようです。

Canister

CanisterはICにデプロイする最小単位のソースコードで、スマートコントラクトとして機能します。

Canister smart contracts | Internet Computer

SDKを使ってコードを書き、デプロイ時にWasmにコンパイルします。

独自言語Motoko*2かRustを第一にサポートしていて、MotokoがネイティブでRusがブリッジの関係にあります。

stackoverflow.blog

それぞれの制約などの比較表がここにあります。

Choosing a programming language | Internet Computer

開発チームは両言語を対等にサポートするよう努めているようですが、学習目的ならRustに慣れている人以外はまずはMotokoを選ぶのがよいです(Rustのcrateをブリッジするレイヤーでたぶんハマるので)。

Internet Identity(認証フレームワーク)

Internet IdentityはブラウザのWebAuthn APIで構築された認証フレームワークです。

認証が独立しているのでユーザー視点で見るとDappを利用するためのブラウザ拡張やウォレットアプリを使った「Connect Wallet」系の操作が不要になります(ICPトークンを利用するためのウォレットは別途あります)。

例えばMacbookChromeでサイト上のボタンを押したらTouch IDを使用してログイン完了、というUXが実現できます。

Bitcoin連携

Internet ComputerにはBitcoinトランザクションを送信できるような連携機能が付いているようです。

Bitcoin Integration — Coding Bitcoin | Internet Computer

該当部分のソースコード を読んでみたところ、共有のCanisterとしてBitcoin用のAPIが実装されているのだという理解をしました。

デプロイ

testnetに相当する専用ネットワークはなく、メインネットに以下のようにエイリアス張って開発しています。

Staging Environment | Internet Computer

メインネットに公開するにはCyclesを支払ってデプロイします。Cyclesはガス代に利用するトークンの名称です。

通常ICPトークンを取引所などで入手して、それをCyclesに交換します。

Mainnet deployment | Internet Computer

ただ現在はDiscord経由でfaucetが機能しており、申請するともらえます。

Getting Started with Free Cycles | Internet Computer

実践編

動くサンプルコードがGitHubにあるのでそれを実際にビルドするのがよいです。

git clone https://github.com/dfinity/examples dfinity/examples

Canisterについて知りたいのならコード量の少ない以下のプロジェクトを掘ってみてください(Rustな人は rust/ ディレクトリに置き換えてください)

❯ du -sh motoko/* | sort
    16K       motoko/calc/
    16K    motoko/counter/
    16K    motoko/echo/
    16K    motoko/factorial/
    16K    motoko/hello-world/
    16K    motoko/http_counter/
    16K    motoko/simple-to-do/
    16K    motoko/whoami/
    16M    motoko/invoice-canister/
    20K    motoko/actor_reference/
    20K    motoko/hello_cycles/
    20K    motoko/pub-sub/
    20K    motoko/quicksort/
    28K    motoko/classes/
    28K    motoko/dip721-nft-container/
    36K    motoko/threshold-ecdsa/
    44K    motoko/basic_bitcoin/
    44K    motoko/basic_dao/
    44K    motoko/ledger-transfer/

個人的なおすすめは「encrypted-notes-dapp」というノートアプリケーションでマルチバイトを保存できなかったりするんだけど、フルセットのCRUDアプリケーションの作り方がわかります。

そしてこのリポジトリは全体的にSvelte好きな人たちによってフロントエンドが書かれていて、USの新しいもの好きな人たちの間ではSvelteのシェアが高いという噂は本当だったのか…… と関心した。

hello

helloプロジェクトの構造がこんな感じです

❯ tree motoko/hello
motoko/hello
├── Makefile
├── README.md
├── dfx.json
├── package-lock.json
├── package.json
├── src
│   ├── hello
│   │   └── main.mo
│   └── hello_assets
│       ├── assets
│       │   ├── favicon.ico
│       │   ├── logo.png
│       │   ├── main.css
│       │   └── sample-asset.txt
│       └── src
│           ├── index.html
│           └── index.js
└── webpack.config.js

src/hello がバックエンドで hello_assets がフロントエンドです。

dfx build すると main.moソースコードがWasmにコンパイルされ、src/declarations/hello/ 以下にJavaScriptから読み込めるインターフェイスを吐いてくれるので、それをフロントエンドで使えます。

定義元のイメージ

actor {
    public func greet(name : Text) : async Text {
        return "Hello, " # name # "!";
    };
};

呼び出し先のコード

import { hello } from "../../declarations/hello";
const greeting = await hello.greet(name);
  1. 書いたコードがWasmになりブロックチェーンネットワーク上で動く
  2. データ永続化もネットワーク内で解決する(Canisterコード上で変数に持つ)
  3. フロントエンドは自動生成されたHTTPクライアントで対話(RPC)

この構図が理解できればEthereumなどと同様に後は一般的なWebアプリケーションと同じアーキテクチャです。作りたいものに応じてサンプルコードをgrepしていけばいいと思います。

疑問点(1): Webアプリケーションとしてのパフォーマンスについて

例えば分散型TwitterであるDistriktの個別ステータスページなんかはPageSpeed InsightsのレポートでLCP30秒ぐらいを出してるけど、はたしてこれはHTTPでブロックチェーンの奥のコードを多段呼び出ししている構造上の問題も含め早くなるんですかね? という部分が一番気になります。

ICに関わらずDappと呼ばれるものの挙動は現状そうなりがちであるけど……

あとはSPAのSSRに相当する手立ては・・? とか

GAFAの支配から逃れ、データを真に所有するためにはしかたがないんやと言われたらまぁ我慢しますけど。

疑問点(2): フロントエンドをデプロイできることの利点は?

前述のフロントエンドをデプロイする先によって制約が生じているけど、アーキテクチャ的には単にHTTP呼び出しなのでフロントエンドだけ別のインフラに乗せることも可能です。

ではその時にCanisterにすることによって得られる恩恵は? という部分。たとえばDapp開発元の手によって管理更新されているとしても、一般的には分散アーキテクチャになっているのでそれがイコール望ましい状態なのかと。

疑問点(3): どこまでが分散アーキテクチャ?

例えばMetamaskに設定したエンドポイントが繋がらなくなっても、エンドポイントBに置き換えてEthereumネットに接続してDappを利用するということはできそうなのだけど、ICでホストされたアプリケーションはic0.app/api のHTTPコールによってすべての機能が動いているように見えるのだけど ic0.app がダウンした時はどうなるの、とか。

まとめ

Internet ComputerはWasmとブロックチェーンを駆使した今時のプラットフォームで、アプリケーション(Dapp)の動作環境になることを全面に打ち出しています。

アプリケーション開発は非常に手軽で、誰でも気軽に試してみることができます。

ユーザーとしてもウォレットなしで試せるアプリケーションが多くてよいですが、分散構造に伴うUXにはまだ懸念点があります。

しかしまぁ今後5年ぐらいはまだまだこのプラットフォームも生きているだろうし、今のうちに遊んでみるのもよいのではないかと思っています。

その他の参考にした記事

qiita.com

*1:WasmでのデプロイはCloudflare Workersなんかもそうです: Introducing workerd: the Open Source Workers runtime

*2:V8/Wasmガチ勢のAndreas RossbergがMotokoを開発している(た?)らしい。