ウォレットレス・オンボーディングのリファレンス実装の解説

Ara
Flow Japan
Published in
10 min readMar 23, 2023

Flow エコシステムでは最近、Flow ハッカソン が開催されました。提出期間はすでに終わり、3/24 に表彰式が行われる予定です。ハッカソンでは、賞金トラックのひとつに「ウォレットレス・オンボーディング」という項目が設けらました。

ウォレットレス・オンボーディングとは、クリプトを知らないユーザーがウォレットを使わずにアプリを使い始めることができて、その後、ウォレットを自分で管理する方向へとスムーズに移行できる設計および構想のことです(詳しくはこちらの記事を参照)。

この記事では、ウォレットレス・オンボーディングの具体的な実装例について、要点を解説します。

※ハッカソンの提出期間終了後、この実装はメインネットにデプロイされました🎉

リファレンス実装

ウォレットレス・オンボーディングの構想は Flow ブロックチェーンの開発初期段階からありました。そのため、これを実現するための主要な技術要素はすでに Flow 上で利用できる状態となっています。例えば、キーペアを複数持つことができ、それらを入れ替えられるアカウントモデルや、アカウントの親子関係をつくるための権限委譲の仕組みなどです。

しかしながら、実用レベルの実装に向けてはまだ模索が必要なフェーズです。本ハッカソンで提示されたリファレンス実装は、これらの技術要素を組み合わせて標準的な規格を意識して設計されたものとなっています。

リファレンス実装の GitHub のリポジトリはこちらです:

リポジトリの README に説明がありますが、これは、バックエンドを必要とせずに、ウォレットレス・オンボーディングを実証し、コンポーザブル・安全・スムーズなオンチェーンゲームの UX を促進するために作られた Flow アプリの例です。

Stripe アカウントの作成と、Google の OAuth 2.0 認証の設定をすれば、ローカルの環境でも動かして試せます。(・・・が、私は Stripe のアカウント作成時に、NFT 関連プロジェクトという理由でアカウントが停止されてしまったため、Stripe の実装部分をコメントアウトして確認しました。)

サンプルアプリの利用フローと設計

この実装例では、ユーザーはまず Google 認証を使ってログインし、アプリのアカウントを作成します。このとき、ユーザーごとに、このアプリ専用の Flow アカウントが作成されます。アプリで使う NFT などのリソースは、基本的にこの Flow アカウント内に保管されます。この状態だと、完全にアプリ側のみがアカウントを管理しています。

ユーザーは、Google 認証でログインしたあと、Blocto や Lilico などの Flow のウォレットを接続できます。このとき、アプリ専用につくられた Flow アカウントを、接続した Flow アカウントの「子アカウント」として紐付けます。子アカウントは、Flow の Cadence 言語が持つ Capability という機能を使うことにより、親アカウントにあらゆる操作権限を委譲します。このプロセスは「アカウントのリンク」と呼ばれます(詳細はこちらのドキュメントを参照)。

アカウントのリンクが行われたあとは、アプリ側は秘密鍵によってこの Flow アカウントを操作でき、また、ユーザー側は委譲された権限によってこの Flow アカウントを操作できることになります。ポイントは、ユーザーが自分のウォレットを持っている場合でも、持っていない場合でも、アプリ専用の Flow アカウントが存在し、 NFT はずっとその専用のアカウント内に保管されることです。ユーザーがあとから自分のウォレットを接続した場合であっても、NFT を移行する操作は行いません。(もちろん技術的には移行することも可能ですが、移行しない方がシームレスにアプリを利用できます。)

補足:この実装例では、アプリ側が、ユーザーのアプリ専用 Flow アカウントの秘密鍵を管理しますが、ユーザー側に秘密鍵を持たせる設計も可能です。こちらのドキュメントに、いくつかのパターンが説明されています

サンプルアプリのデモ動画はこちらです。UI をみるとイメージが湧くと思います。

ChildAccount コントラクト

ではここから、子アカウントと親アカウントの関係を実現するためのスマートコントラクトについて説明します。

サンプルアプリを含むコードはこちら:

スマートコントラクトだけみたい方はこちらを参照してください:

これは、ChildAccount という名前のスマートコントラクトで、ウォレットレス・オンボーディングを実現するための標準的な規格を目指してつくられたものになっています。注意点として、この実装はまだ検証中のものであり、ハッカソンなどでのフィードバックを受けながら、変更されていく可能性が高いです。

ChildAccount コントラクトには、2 つの主要なリソースが定義されています。

  • ChildAccountManager : 親アカウントが持つことになるリソース。紐づけられている子アカウントの操作権限(AuthAccount の Capability)を含んでいる。
  • ChildAccountTag : 子アカウントが持つことになるリソース。親アカウントに特定の権限(任意の Capability)を使わせることができるように設計されている。

子アカウントと親アカウントは、例えば以下の図のような関係になります。ユーザーが鍵を管理しているアカウント(User’s Account)が親アカウントとなり、dApp 側が鍵を管理しているアカウント(Child Account)が子アカウントとなります。

※これはあくまで構成例のひとつであり、同じ ChildAccount コントラクトを使って、子アカウント/親アカウントを逆にしたり、鍵管理を一箇所にすることもできます。

子アカウントの作成

これまで「子アカウント」「親アカウント」という呼び方をしていましたが、これらの実態はどちらも(普通の)Flow アカウントです。構成によっては、あるアカウントが親でもあり子でもあることがありえます。

子アカウントをつくるタイミングと方法はアプリによって異なりますが、ウォレットレス・オンボーディングのアプリではほとんどの場合、ユーザーが Google 認証などでアプリのアカウントを作成したタイミングに、アプリの管理アカウントから Flow アカウントを作成することになるでしょう。トランザクション例はこちらです。アプリの管理アカウントからユーザーの子アカウントを作る場合、 ChildAccountCreator というリソースが使われます。この場合、子アカウントの作成した時点では、親アカウントが紐づいていません。ユーザーがあとでウォレットを接続したときに、このようなマルチパーティのトランザクションを送信して親アカウントを紐付けます。

一方、アプリ利用開始時点からユーザーにウォレットを接続させる場合、ユーザーからのトランザクション送信で子アカウントを作成させることも可能です。トランザクション例はこちらです。この場合、各ユーザーのアカウントに保管した ChildAccountManager というリソースが使われます。

子アカウントの操作

子アカウントを操作する方法は大きく二つあります。

  1. 子アカウントの秘密鍵を使ってトランザクションを送信する
  2. 親アカウントが、子アカウントの操作権限(AuthAccount の Capability)を利用するトランザクションを送信する

1 は、通常のトランザクションと同じです。2 は、親アカウントのストレージ内に保持する ChildAccountManager に含まれる Capability<&AuthAccount> を利用します。トランザクションの例はこちら

AuthAccount の Capability について

Flow では、アカウントごとに用意されたストレージを操作して、そこに様々なリソースを保管します。これを行うために、アカウントのストレージを操作するための AuthAccount というオブジェクト が用意されています。このオブジェクトは通常、トランザクションに署名したアカウントのものが、そのトランザクション内で利用できる状態になっています。

さらに発展的な使い方として、以下のようなトランザクションを送ると、AuthAccount を操作するための Capability 型のオブジェクトを取得できます(詳細はこちら)。ChildAccount コントラクトにおいても、この Capability オブジェクトが利用されています。

transaction {
prepare(signer: AuthAccount) {
if !signer.getCapability<&AuthAccount>(/private/YourAuthAccountCapabilityPath).check() {
// If not, unlink anything that may be there and link the AuthAccount Capability
signer.unlink(linkpath)
signer.linkAccount(linkPath)
}
}
}

おわりに

ユーザーにウォレットを意識させないウォレットレス・オンボーディングを実現するには追加の実装が必要で複雑性が増しますが、このコントラクトを利用すると複雑性を抑えられます。

今回のハッカソンでは 20 を超えるプロジェクトで ChildAccount コントラクトが使われたようです。様々なフィードバックを受けて、より使いやすいものに改善されていくとよいと思います。AuthAccount を使った権限委譲の仕組みは非常にスマートで、セキュリティ的にも好ましいと感じます。今後、より普及していくことを期待しています。

こちらのポータルサイト https://flow.com/hybrid-custody に情報がまとまっているので、さらに詳しいことが知りたい方、実装してみたい方はぜひご覧ください。

--

--

Ara
Flow Japan

ソフトウェアエンジニア。生物学、民俗学、仏教、神道、メディアアート、博物学、フォント、ブロックチェーンなどに興味あり。