Move の支持者として、開発者に Move を推奨するたびに、こうした質問に直面します。Move にはどんな利点がありますか?なぜ Move なのですか?まるで友人に新しい恋人を紹介する時に似たような質問が出てくるようです。しかし、このような質問には簡単には答えられません。利点と欠点を一つ一つ挙げていくと、必ず誰かが疑問を持つでしょう。結局、新しい言語のエコシステムは成熟しておらず、選択はその潜在能力に基づいて判断するしかありません。まず一つの結論を述べます:Move は Solidity のようなエコシステムを構築する最も有望な言語であり、さらにはそれを超えるスマートコントラクトプログラミング言語です。
目標読者:開発者およびブロックチェーン分野の技術に興味のある友人。この記事では、スマートコントラクトが現在直面している課題と Move のいくつかの試みをできるだけ分かりやすく説明し、コードをあまり使用せず、プログラミング言語を理解していない友人でも大まかに理解できることを期待していますが、これは非常に難しいことですので、読者からのフィードバックをお願いしたいです。
スマートコントラクトの二つの道#
数年前に時間を戻すと、新しいパブリックチェーンでチューリング完全なスマートコントラクトをサポートするプログラミング言語には主に二つの方法がありました:
一つは、既存のプログラミング言語を基にしてカスタマイズし、WASM などの汎用仮想マシンで実行する方法です。この方法の利点は、現在のプログラミング言語と WASM 仮想マシンのエコシステムを活用できることです。
もう一つは、専用のスマートコントラクトプログラミング言語と仮想マシンを新たに作り、言語と仮想マシンのエコシステムをゼロから構築する方法です。Solidity はこのルートを選び、Move も同様です。
当時、多くの人は Solidity&EVM エコシステムにあまり期待していませんでした。Solidity はトークンを発行する以外にはあまり役に立たないように見え、性能も良くなく、ツールも弱く、まるでおもちゃのようでした。多くのチェーンの目標は、開発者が既存の言語を使ってスマートコントラクトをプログラミングできるようにすることで、前者の道がより期待されていました。新しいパブリックチェーンが直接 Solidity&EVM をコピーすることはほとんどありませんでした。
しかし、数年の発展を経て、特に DeFi の台頭後、突然 Solidity のエコシステムが変わったことに気づきました。一方で、前者の道を選んだスマートコントラクトエコシステムは成長しませんでした。なぜでしょうか?私がまとめた理由はいくつかあります。
- ブロックチェーンのプログラム実行環境とオペレーティングシステム向けのプログラム実行環境には大きな違いがあります。オペレーティングシステムの呼び出し、ファイル IO、ハードウェア、ネットワーク、並行処理などの関連ライブラリを捨て、チェーン上の実行コストを考慮すると、既存のプログラミング言語がスマートコントラクトと共有できるコードライブラリは非常に少ないです。
- 第一の方法は理論的には多くの言語をサポートできますが、実際には Runtime を持つプログラミング言語が WASM などの仮想マシンにコンパイルされると、ファイルが非常に大きくなり、ブロックチェーンのシーンでの使用には適していません。使用できるのは主に C、C++、Rust などです。これらの言語の学習コストは、Solidity のような専用のスマートコントラクトプログラミング言語よりも低くはなく、複数の言語を同時にサポートすると、初期のエコシステムの分断を引き起こす可能性があります。
- 各チェーンの状態処理メカニズムは異なり、たとえすべてが WASM 仮想マシンを使用していても、各チェーンのスマートコントラクトアプリケーションは直接移行できず、共通のプログラミング言語や開発者エコシステムを共有することができません。
アプリケーション開発者にとって、直接向き合うのはスマートコントラクトプログラミング言語、プログラミング言語の基礎ライブラリ、再利用可能なオープンソースライブラリの有無です。DeFi の安全性は、スマートコントラクトコードが監査を受けることを要求し、監査されたコードの各行はお金を表します。既存のコードを少し変更してコピーすることで、監査コストを削減できます。
今振り返ると、Solidity は一見遅い道を歩んでいるように見えますが、実際にはエコシステムをより早く構築しました。今では多くの人が Solidity&EVM がスマートコントラクトの終着点だと考え、多くのチェーンが Solidity&EVM を互換性を持たせたり移植したりし始めています。この時、新しいスマートコントラクトプログラミング言語は、自身がより強力なエコシステム構築能力を持っていることを証明する必要があります。そうでなければ、皆が関心を持ち、投資することを納得させることはできません。
新たな疑問は、プログラミング言語のエコシステム構築能力をどのように評価するかということです。
プログラミング言語のエコシステム構築能力#
プログラミング言語のエコシステム構築能力は、簡単に言えば、そのコードの再利用能力であり、主に二つの側面に現れます:
- プログラミング言語モジュール間の依存関係の方式。
- プログラミング言語モジュール間の組み合わせの方式。「可組み合わせ性」はスマートコントラクトが誇る特性ですが、実際にはすべてのプログラミング言語には組み合わせ性があります。私たちが発明した Interface や Trait などは、より便利に組み合わせるためのものです。
まず依存関係の方式について説明します。プログラミング言語が依存関係を実現する主な方法は三つあります:
- 静的ライブラリ(Static-Libraries)を通じて、コンパイル時に静的リンクし、依存関係を同じバイナリにパッケージ化します。
- 動的ライブラリ(Dynamic-Libraries)を通じて、実行時に動的リンクし、依存関係はバイナリには含まれませんが、事前にターゲットプラットフォームにデプロイする必要があります。
- リモート呼び出し(RPC)を通じて実行時に依存します。ここでは、リモート呼び出し可能な API を指します。
1 と 2 は一般的に基礎ライブラリ依存のシーンで使用されます。基礎ライブラリは一般的に無状態であり、アプリケーションが状態をどのように処理するか(どのファイルに書き込むか、どのデータベーステーブルに保存するか)は、基礎ライブラリでは仮定することが非常に難しいです。この呼び出しは、同じプロセス内の同じメソッド呼び出しのコンテキスト内で行われ、呼び出しスタックを共有し、メモリ空間を共有し、安全な隔離がありません(または隔離が非常に弱い)ため、信頼できる環境が必要です。
3 は実際には別のプロセスまたは別のマシン上のプロセスを呼び出し、相互にメッセージ通信を行い、各プロセスが自分の状態を担当するため、状態の依存関係を提供でき、呼び出しには安全な隔離があります。
これら三つの方法にはそれぞれ利点と欠点があります。1 は最終的なバイナリに依存ライブラリを含めるため、利点はターゲットプラットフォームの環境に依存しないことですが、欠点はバイナリが大きくなることです。2 の利点はバイナリが小さいことですが、実行環境に前提条件があります。3 は言語を超えた依存関係を構築でき、一般的にはサービス間や機関間の協力のシーンで使用され、開発者が呼び出しやすくするために、一般的には SDK やコード生成を通じてメソッド呼び出しのようにシミュレートされます。
技術の歴史の中で、多くのプログラミング言語やオペレーティングシステムプラットフォームが、リモート呼び出しとローカル呼び出しの間の差異を埋めるために多大な努力を費やし、シームレスなリモート呼び出しと組み合わせを実現しようとしました。COM(Component Object Model)や CORBA、SOAP、REST などの著名な技術用語は、これらの問題を解決するために存在します。シームレスな呼び出しと組み合わせの夢は破れましたが、最終的にはエンジニアの手作業でインターフェースをつなぎ合わせて Web2 のサービスを統合しましたが、夢の火種はまだ残っています。
そしてスマートコントラクトは、アプリケーション間の依存関係の方式に新たな変化をもたらしました。
スマートコントラクトがもたらす変化#
従来の企業アプリケーション間の依存関係の方式は、以下の図で表すことができます:
- システムはさまざまな RPC プロトコルを通じて、異なるマシン上で実行されているサービスを接続します。
- マシン間にはさまざまな技術的、人的な「壁」が隔離を行い、安全性を確保します。
スマートコントラクトの実行環境は、チェーンのノードによって構築されたサンドボックス環境であり、複数のコントラクトプログラムは同じプロセス内の異なる仮想マシンサンドボックスで実行されます。以下の図に示すように:
- コントラクト間の呼び出しは、同じプロセス内の異なるスマートコントラクト仮想マシン間の呼び出しです。
- 安全性はスマートコントラクト仮想マシン間の隔離に依存します。
Solidity を例に挙げると、Solidity のコントラクト(contract
として示されるモジュール)は、自分の関数をpublic
として宣言し、他のコントラクトはこのpublic
メソッドを通じてそのコントラクトを直接呼び出すことができます。以下の図は RPC 呼び出しのプロセスの一例です:
画像出典 https://docs.microsoft.com/en-us/windows/win32/rpc/how-rpc-works
チェーンは実際に上図の Client と Server 間の通信のすべてのプロセスを引き受け、スタブを自動生成し、シリアル化とデシリアル化を実現し、開発者にとってリモート呼び出しがローカルメソッド呼び出しのように感じられるようにします。
もちろん、技術には銀の弾丸はなく、一度で解決する方法はありません。新しい方法は常に新しい課題を解決する必要があります。
スマートコントラクトの依存の課題#
前述の分析を通じて、スマートコントラクト間の呼び出しは実際にはリモート呼び出しに似た方法であることを理解しました。それでは、ライブラリの方式で依存呼び出しを行うことはできるのでしょうか?
Solidity では、library
として示されるモジュールは、静的ライブラリに相当し、無状態でなければなりません。library
への依存はコンパイル時に最終的なコントラクトのバイナリにパッケージ化されます。
これがもたらす問題は、コントラクトが複雑で依存関係が多すぎると、コンパイル後のコントラクトが大きくなり、デプロイできなくなることです。しかし、複数のコントラクトに分割すると、状態を直接共有できず、内部依存がリモートサービス間の依存に変わり、呼び出しコストが増加します。
では、動的ライブラリのロードの道を選ぶことはできないのでしょうか?たとえば、Ethereum 上のほとんどのコントラクトは SafeMath.sol というライブラリに依存しており、各コントラクトはそのバイナリを含んでいます。コードがチェーン上にあるのなら、なぜ直接共有できないのでしょうか?
そこで Solidity はdelegatecall
という方法を提供し、動的リンクライブラリの解決策に似て、別のコントラクトのコードを現在のコントラクトの呼び出しコンテキストに埋め込んで実行し、別のコントラクトが現在のコントラクトの状態を直接読み書きできるようにします。しかし、これには二つの要件があります:
- 呼び出し元と呼び出し先は完全に信頼できる関係でなければならない。
- 二つのコントラクトの状態は整合している必要があります。
非スマートコントラクト開発者にはこの問題が理解しにくいかもしれませんが、Java 開発者であればこう理解できます:Solidity の各コントラクトは一つの Class に相当し、デプロイ後に実行されるのは単一の Object です。実行時に別の Class のメソッドをロードして現在の Object の属性を変更したい場合、二つの Class で定義されたフィールドは同じでなければならず、新しくロードされたメソッドは内部メソッドに相当し、Object の内部属性は完全にそれに見えます。
このようにして、動的リンクの使用シーンと再利用の程度が制限され、現在は主に内部のコントラクトアップグレードに使用されています。
上記の理由から、Solidity は他のプログラミング言語のように豊富な標準ライブラリ(stdlib)を提供することが非常に難しく、他のコントラクトが依存するために事前にチェーン上にデプロイすることはできず、限られた数のプリコンパイルメソッドしか提供できません。
これにより EVM バイトコードの膨張が引き起こされます。本来 Solidity コードを通じて状態から取得できるデータが、実行時コンテキストから取得するために仮想マシン命令として実装されざるを得なくなります。たとえば、ブロック関連の情報は本来、標準ライブラリ内のシステムコントラクトから状態を取得できるはずで、プログラミング言語自体がブロック関連の情報を知る必要はありません。
この問題はすべてのチェーンとスマートコントラクトプログラミング言語が直面する問題です。従来のプログラミング言語は、同じメソッド呼び出しスタック内の安全性の問題をあまり考慮しておらず(あるいはあまり考慮していない)、チェーンに移行した後も、依存関係を解決するためには静的依存とリモート依存の方式しか提供できず、Solidity のdelegatecall
のような解決策を提供することすら非常に難しいです。
では、スマートコントラクト間で動的ライブラリリンクのような呼び出しを実現するにはどうすればよいのでしょうか?コントラクト間の呼び出しが同じメソッド呼び出しスタックを共有し、変数を直接渡すことができるのでしょうか?
このようにすることで、二つの安全性の課題が生じます:
- コントラクトの状態の安全性は、プログラミング言語内部の安全性によって隔離される必要があり、仮想マシンによる隔離に依存してはいけません。
- コントラクト間の変数の渡しは安全である必要があり、無闇に捨てられないこと、特に資産タイプの変数については保証される必要があります。
スマートコントラクトの状態隔離#
前述のように、スマートコントラクトは実際には異なる組織のコードを同じプロセス内で実行するため、コントラクトの状態(簡単に言えば、コントラクト実行時に生成された結果で、次回実行時に使用するために保存する必要がある)の隔離が必要です。もし一つのコントラクトが別のコントラクトの状態を読み書きできることを直接許可すると、安全性の問題が生じることは明らかです。
隔離の方法は理解するのが非常に簡単で、各コントラクトに独立した状態空間を与えることです。スマートコントラクトを実行する際に、現在のスマートコントラクトの状態空間を仮想マシンにバインドし、スマートコントラクトは自分の状態のみを読み取ることができるようにします。別のコントラクトを読み取る必要がある場合は、前述のコントラクト間の呼び出しが必要であり、実際には別の仮想マシンで実行されます。
しかし、動的ライブラリの方式で依存を行おうとすると、このような隔離では不十分です。なぜなら、実際には別のコントラクトが現在のコントラクトの実行スタック内で実行されているからです。私たちは言語レベルでの隔離を必要とし、仮想マシンの隔離では不十分です。
さらに、コントラクトの状態空間の隔離は、状態の所有権の問題をもたらします。この場合、すべての状態はコントラクトに属し、コントラクトの公共状態と個人の状態を区別していないため、状態の課金に難題をもたらし、長期的には状態の爆発問題が生じる可能性があります。
では、スマートコントラクトの言語レベルで状態隔離をどのように実現すればよいのでしょうか?実際には、タイプに基づいて行うことができます。
- プログラミング言語が提供するタイプの可視性の制約を利用します。この特性はほとんどのプログラミング言語がサポートしています。
- プログラミング言語が提供する変数の可変性の制約を利用します。多くのプログラミング言語は、参照の可変と不可変を区別します(例えば Rust)。
- タイプをキーとした外部ストレージを提供し、現在のモジュールが自分で定義したタイプのみをキーとして外部ストレージを読み取ることを制限します。
- プログラミング言語レベルでタイプに対して
copy
やdrop
を宣言する能力を提供し、資産タイプの変数が無闇にコピーされたり捨てられたりしないことを保証します。
Move 言語は、上記の解決策を採用しています。特に 3 と 4 は Move 特有のものです。この解決策は理解しやすいもので、仮想マシンレベルで各スマートコントラクトプログラムに独自の状態空間を与えることができない場合、コントラクト内部で状態隔離を行うことは、タイプに基づく方法が比較的理解しやすいからです。なぜなら、タイプには明確な帰属と可視性があるからです。
このようにして、Move ではスマートコントラクト間の呼び出しが以下の図のようになります:
異なる組織や機関のプログラムが、動的ライブラリの方式で組み合わさり、同じアプリケーションとして実行され、同じプログラミング言語のメモリ空間を共有します。組織間の相互作用のルールとプロトコルは、プログラミング言語のルールによってのみ制約されます。(資源の定義については後述します)。
この変化は、いくつかの側面で変化をもたらします:
- プログラミング言語とチェーンは、機能豊富な基礎ライブラリを提供し、事前にチェーン上にデプロイできます。アプリケーションは直接依存して再利用でき、基礎ライブラリ部分を自分のバイナリに含める必要はありません。
- 異なる組織間のコードが同じプログラミング言語のメモリ空間の状態にあるため、より豊かで複雑な組み合わせの方法を提供できます。このトピックは後で詳述します。
Move のこの依存方式は、動的ライブラリのモデルに似ていますが、同時にチェーンの状態管理の特性を利用し、プログラミング言語に新しい依存モデルをもたらしました。
このモデルでは、チェーンはスマートコントラクトの実行環境であると同時に、スマートコントラクトプログラムのバイナリリポジトリでもあります。開発者は依存を通じてチェーン上のスマートコントラクトを自由に組み合わせて新しいスマートコントラクトプログラムを提供でき、この依存関係はチェーン上で追跡可能です。
もちろん、Move はまだ初期段階であり、この依存方式が提供する能力はまだ十分に発揮されていませんが、雛形は現れています。将来的には、依存関係に基づくインセンティブメカニズムや、このインセンティブモデルに基づいて構築された新しいオープンソースエコシステムが登場することが期待されます。後で「可組み合わせ性」についてさらに話しましょう。
スマートコントラクトの可組み合わせ性#
プログラミング言語モジュール間の可組み合わせ性は、プログラミング言語エコシステムを構築するもう一つの重要な特性です。モジュール間に可組み合わせ性があるからこそ、依存関係が生まれ、異なる依存方式が異なる組み合わせ能力を提供します。
前述の依存方式の分析に基づくと、Solidity エコシステムにおけるスマートコントラクトの可組み合わせ性について話すとき、実際にはcontract
間の組み合わせについて言及しており、library
間の組み合わせについては言及していません。また、前述のように、contract
間の依存はリモート呼び出しに似た依存であり、実際にやり取りされるのはメッセージであり、参照
や資源
ではありません。
ここで資源(resource)
という言葉を使うのは、プログラム内でこのタイプの変数を無闇にコピー (copy) したり捨て (drop) たりできないことを強調するためです。これは線形タイプによる特性であり、この概念はプログラミング言語の中ではまだ普及していません。
線形タイプは線形論理に由来し、線形論理自体は古典論理では表現できない資源消費に関する論理を表現するために存在します。たとえば「牛乳」があれば、論理的には「チーズ」を導き出すことができますが、ここでは資源消費を表現することができず、X 単位の「牛乳」が Y 単位の「チーズ」を得ることができるという論理を表現できません。これが線形論理の必要性であり、プログラミング言語にも線形タイプが存在します。
プログラミング言語で最初に扱う資源はメモリであるため、線形タイプの一つの適用シーンはメモリの使用を追跡し、メモリ資源が正しく回収されることを保証することです。たとえば Rust ですが、この特性を普遍的に広めることができれば、プログラム内で任意のタイプの資源
を模擬し、表現することができます。
では、なぜ組み合わせ時に資源
の渡しが非常に重要なのでしょうか?まず、現在の Interface に基づく組み合わせ方式を理解しましょう。ほとんどのプログラミング言語、Solidity を含めて、こうした組み合わせ方式を採用しています。
複数のモジュールを組み合わせるためには、最も重要なのは呼び出す関数とその関数の引数および戻り値のタイプを事前に合意することです。一般的にこれを関数の「シグネチャ」と呼びます。私たちは通常 Interface を使ってこの制約を定義しますが、具体的な実装は各自が行います。
たとえば、よく知られている ERC20 トークンは Interface であり、以下のメソッドを提供します:
function balanceOf(address _owner) public view returns (uint256 balance)
function transfer(address _to, uint256 _value) public returns (bool success)
このインターフェースの定義には、特定のアドレスに送金するメソッドや残高を照会するメソッドが含まれていますが、直接引き出す(withdraw)メソッドはありません。なぜなら、Solidity ではトークンはサービスであり、タイプではないからです。以下は Move で定義された類似のメソッドです:
module Token{
struct Token<TokenType>{
value: u128,
}
}
module Account{
withdraw(sender: &signer, amount):Token<STC>;
deposit(receiver: address, token: Token<STC>);
transfer(sender, receiver, amount);
}
ここで、Token は一つのタイプであり、アカウントから Token オブジェクトを引き出すことができます。これを行う意義は何でしょうか?
ここで、二者の組み合わせ方式の違いを比較するために、比較的分かりやすい類比を用いることができます。Token オブジェクトは、生活の中の現金に似ています。あなたが商場で物を購入したい場合、二つの支払い方法があります:
- 商場と銀行がインターフェースを接続し、電子決済システムを導入します。あなたが支払うとき、銀行に商場に振り込むように直接リクエストを送ります。
- あなたが銀行から現金を引き出し、商場で直接支払います。この場合、商場は銀行と事前にインターフェースを接続する必要はなく、ただ現金タイプを受け入れるだけで済みます。現金を受け取った後、商場がその現金を金庫に保管するか、銀行に預けるかは商場の自由です。
後者の組み合わせタイプは、資源タイプに基づく組み合わせ方式と呼ぶことができます。異なる組織のコントラクト間で流動する資源を「自由状態」と呼ぶことができます。
自由状態に基づく組み合わせ方式は、物理的な世界の組み合わせ方式に似ています。たとえば、CD とプレーヤー、さまざまな機械の部品などです。この組み合わせ方式は、インターフェースに基づく組み合わせ方式と矛盾するものではありません。たとえば、複数の取引所(swap)が外部に統一されたインターフェースを提供し、第三者の統合を容易にする場合、インターフェースに基づく組み合わせ方式がより適しています。
自由状態に基づく組み合わせの主な利点は二つあります:
- インターフェースに基づく組み合わせのネストの深さを効果的に低下させることができます。この点に興味がある方は、以前の私の発表の中でのフラッシュローンの例を参照してください。読者の中にはフラッシュローンの背景を知らない方もいると思いますので、ここでは詳述しません。
- 資源の定義と資源に基づく行動を明確に分離できます。ここでの典型的な例は、ソウルバウンド NFT です。
ソウルバウンド NFT という概念は Vitalik が提唱したもので、NFT を使ってアイデンティティ関係を表現しようとしています。この関係は譲渡可能であってはならず、たとえば卒業証書や名誉証明書などです。
ETH 上の NFT 標準はすべてインターフェースであり、たとえば ERC721 のいくつかのメソッドは以下の通りです:
function ownerOf(uint256 _tokenId) external view returns (address);
function safeTransferFrom(address _from, address _to, uint256 _tokenId) external payable;
新しい行動を拡張したい場合、たとえばバインドする場合は、新しいインターフェースを定義する必要があります。古いメソッドにも影響を与えます。たとえば、NFT がすでにソウルバウンドされている場合、NFT を譲渡することはできません。これは必然的に互換性の問題を引き起こします。さらに難しいのは、譲渡を許可するが、バインド後は流通できなくなるシーンです。たとえば、一部のゲームアイテムなどです。
しかし、NFT を一つの物品と考えると、その物品自体はどのように表示され、どのような属性を持つかを決定するだけであり、譲渡可能かどうかは上層のラッピングによって決まるべきです。
たとえば、以下は Move で定義された NFT であり、これは一つのタイプです。
struct NFT<NFTMeta: copy + store + drop, NFTBody: store> has store {
creator: address,
id: u64,
base_meta: Metadata,
type_meta: NFTMeta,
body: NFTBody,
}
次に、上層のラッピングを異なるコンテナとして考えることができます。異なるコンテナは異なる行動を持ちます。たとえば、NFT が個人の展示館に置かれているときは取り出せますが、特定のコンテナに置かれると、取り出すには他のルールが必要になります。これが「バインド」を実現します。
たとえば、Starcoin の NFT 標準は、IdentifierNFT
というソウルバウンド NFT のコンテナを実装しています:
/// IdentifierNFTにはOptionのNFTが含まれており、デフォルトは空で、NFTを収容できる箱のようなものです。
struct IdentifierNFT<NFTMeta: copy + store + drop, NFTBody: store> has key {
nft: Option<NFT<NFTMeta, NFTBody>>,
}
/// ユーザーはAcceptメソッドを通じて、自分のアカウントに空のIdentifierNFTを初期化します。
public fun accept<NFTMeta: copy + store + drop, NFTBody: store>(sender: &signer) {
move_to(sender, IdentifierNFT<NFTMeta, NFTBody> {
nft: Option::none(),
});
}
/// 開発者はMintCapabilityを通じてreceiverにそのnftを付与し、nftをIdentifierNFTに埋め込みます。
public fun grant_to<NFTMeta: copy + store + drop, NFTBody: store>(_cap: &mut MintCapability<NFTMeta>, receiver: address, nft: NFT<NFTMeta, NFTBody>) acquires IdentifierNFT {
let id_nft = borrow_global_mut<IdentifierNFT<NFTMeta, NFTBody>>(receiver);
Option::fill(&mut id_nft.nft, nft);
}
/// 開発者はBurnCapabilityを通じて`owner`のIdentifierNFTからNFTを取り出すこともできます。
public fun revoke<NFTMeta: copy + store + drop, NFTBody: store>(_cap: &mut BurnCapability<NFTMeta>, owner: address): NFT<NFTMeta, NFTBody> acquires IdentifierNFT {
let id_nft = move_from<IdentifierNFT<NFTMeta, NFTBody>>(owner);
let IdentifierNFT { nft } = id_nft;
Option::destroy_some(nft)
}
この箱の中の NFT は、NFT の発行者だけが付与または取り消すことができ、ユーザー自身は受け入れるかどうかを決定することができます。たとえば、卒業証書は学校が発行し、取り消すことができます。もちろん、開発者は他のルールのコンテナを実装することもできますが、NFT 標準は統一されています。この具体的な実装に興味がある方は、文末のリンクを参照してください。
この部分では、Move が線形タイプに基づいて新しい組み合わせ方式をもたらすことを説明しました。もちろん、言語の特性だけではプログラミング言語のエコシステムを自然に生み出すことはできず、適用シーンが必要です。Move 言語の適用シーンの拡張についてさらに議論しましょう。
スマートコントラクトの適用シーンの拡張#
Move はもともと Libra チェーンのスマートコントラクトプログラミング言語として設計されており、異なる適用シーンを考慮していました。当時、Starcoin はちょうど設計中であり、その特性が Starcoin の追求する目標に合致していたため、パブリックチェーンのシーンでその適用が決まりました。その後、Libra プロジェクトが頓挫し、いくつかのパブリックチェーンプロジェクトが孵化し、異なる方向で探求が行われました:
- MystenLabs の Sui は不変状態を導入し、Move で UTXO に似たプログラミングモデルを実現しようとしています。
- Aptos は Layer1 上でのトランザクションの並行実行と高性能を探求しています。
- Pontem は Move を Polkadot エコシステムに持ち込もうとしています。
- Starcoin は Layer2 や Layer3 の階層的拡張モデルを探求しています。
同時に、Meta(Facebook)の元 Move チームは、Move を EVM 上で実行しようとしています。これにより、コントラクト間の資源
の伝達特性は失われますが、Move エコシステムの拡張や Move エコシステムと Solidity エコシステムの融合に役立ちます。
現在、Move プロジェクトは独立し、完全にコミュニティ主導のプログラミング言語として存在しています。現在、いくつかの課題に直面しています:
- 異なるチェーンのニーズの間で最大公約数を見つける方法は?言語の汎用性を保証するために。
- 異なるチェーンが独自の特殊な言語拡張を実現する方法は?
- 複数のチェーン間で基礎ライブラリやアプリケーションエコシステムを共有する方法は?
これらの課題は同時に機会でもあり、相互に対立するものであり、選択が必要であり、発展の中でバランスを見つける必要があります。これまでにこのような試みを行った言語はありません。このバランスは、Move が単にブロックチェーンに結びつくだけでなく、より多くの適用シーンを探求する可能性を保証します。
この点で、Solidity は命令とチェーンの相互作用によって生じる問題として、Solidity&EVM エコシステムが完全にチェーンに結びついているため、実行にはチェーンの環境をシミュレートする必要があります。これにより、Solidity が他のシーンに拡張されることが制限されます。
スマートコントラクトプログラミング言語の未来については、多くの異なる見解がありますが、大体において四つのタイプがあります:
- チューリング完全なスマートコントラクト言語は必要なく、Bitcoin のようなスクリプトで十分です。チューリング完全なスマートコントラクトがなければ、一般的な仲裁能力を実現することは難しく、チェーンの適用シーンを制限します。これについては、以前の私の文章「ビットコインスマートコントラクトの『三つの鍵』を開く」を参照できます。
- 専用のスマートコントラクト言語は必要なく、既存のプログラミング言語で十分です。この見解については、上記で分析しました。
- チューリング完全なスマートコントラクト言語が必要ですが、適用シーンはチェーン上に限られ、データベース内のストアドプロシージャスクリプトに似ています。これは現在のスマートコントラクト開発者の大多数の見解です。
- スマートコントラクトプログラミング言語は他のシーンに拡張され、最終的には一般的なプログラミング言語に変わるでしょう。
最後の見解は、スマートコントラクト言語の最大化主義者と呼ぶことができ、私はこの見解を持っています。その理由は非常に簡単です。Web3 の世界では、ゲームや他のアプリケーションにおいて、争議が発生した場合、デジタルな争議仲裁の解決策が必要です。ブロックチェーンとスマートコントラクトの重要な技術的ポイントは、状態と計算の証明に関するものであり、現在この分野で模索されている仲裁メカニズムは、より一般的なシーンにも適用できるものです。ユーザーがアプリケーションをインストールし、そのアプリケーションが安全でないことを心配し、アプリケーションが状態と計算の証明を提供できることを望むとき、アプリケーション開発者はスマートコントラクトを使用してアプリケーションのコアロジックを実装する必要があります。
まとめ#
この記事では、チェーン上のスマートコントラクトの実現方法と、現在スマートコントラクトが依存関係や可組み合わせ性において直面している課題について、できるだけ分かりやすい言葉で Move がこの方向で行った試みと、それに基づくエコシステム構築の可能性を説明しました。
記事が長くなったため、多くの側面がまだ表現されていません。このテーマに基づいてシリーズを書こうと思っていますので、ここで予告します:
なぜ Move なのか:エコシステム構築能力#
これはこの記事です。
なぜ Move なのか:スマートコントラクトの安全性#
スマートコントラクトの安全性は広く注目されている問題であり、Move を布教する記事でも「安全性」という特性がよく言及されます。しかし、異なるプログラミング言語間の安全性をどのように比較するのでしょうか?「自分の足に銃を撃つことを止めることはできない」という言葉があります。プログラミング言語はツールであり、開発者がこのツールを使って自分の足に銃を撃つとき、プログラミング言語自体は何をすることができるのでしょうか?スマートコントラクトは異なる組織のプログラムを同じプロセス内で実行するため、プログラミング言語の役割を最大化しますが、新たな安全性の課題ももたらします。この記事では、この問題を全体的な視点から議論します。
なぜ Move なのか:状態爆発と階層化#
Move はプログラミング言語内部で状態隔離を実現し、この分野の解決策にさらなる可能性を提供します。コントラクトは状態の保存位置をより自由に処理でき、たとえばユーザー自身の状態空間に状態を保存することができ、これにより状態の課金が実現し、ユーザーがスペースを解放するインセンティブを与えることができます。たとえば、状態が異なる層間で移動することが本当に実現できるのか、Layer1 の状態を Layer2 に移行することができるのか、根本的に状態爆発問題を解決することができるのか?この記事では、この方向のいくつかの可能性を探ります。
今後の内容に興味がある方は、以下の方法で私をフォローできます:
- Twitter: @jolestar
- 微博:@jolestar
- Telegram チャンネル: https://t.me/jolestarblog
原始リンク:
https://jolestar.com/why-move-1/
関連リンク#
- https://github.com/move-language/move Move プロジェクトの新しいリポジトリ
- awesome-move: Code and content from the Move community Move に関連するプロジェクトのリソース集、パブリックチェーンや Move 実装のライブラリを含む
- Soulbound (vitalik.ca) Vitalik による NFT ソウルバウンドに関する記事
- SIP22 NFT Starcoin の NFT 標準、IdentifierNFT の説明を含む
- ビットコインスマートコントラクトの「三つの鍵」を開く (jolestar.com)