見出し画像

【Sui】スマート・コントラクト開発 - MoveとRustの比較(導入〜SolanaとMoveのプログラミングモデル)

この記事は、 Krešimir Klas さんが執筆した "Smart Contract Development — Move vs. Rust" (2022年9月7日公開) という記事を、本人の許可をいただいた上で翻訳・補足したものです。

1. 導入

ここ最近、高性能のL1である AptosSui、そしてこれらの新興チェーンには不可欠な存在である Move というプログラミング言語が話題になっている。開発者の中には、Moveがスマートコントラクト開発の未来だと断言し積極的に使用する人もいれば、Moveは単なるスマートコントラクトのプログラミング言語のひとつであり、根本的には既存のプログラミングモデルとあまり変わらないという慎重な印象を持つ人もいます。暗号資産投資家も、これらの新しいL1の何が特別なのか、そして高性能L1の代表格であるSolana (プログラミング言語に Rust を採用) とどのように比較されるのか疑問に思っている。

💡 Rust は Firefox の開発元である Mozilla が中心となり、オープンソースで開発されている汎用プログラミング言語です。C++に匹敵する実行速度や詳細なメモリ管理が実現できます。

しかし、この新しい技術が何をもたらすのか十分に理解できるまでの深い議論はまだされていない。Move懐疑論者は、Moveの掴みづらい(しかしとても重要な)側面のいくつかを十分に理解することなくMoveを軽視し、MoveファンはMoveを限りなく賞賛するが、それがなぜ素晴らしいのかを十分には説明できない。このため、この議論を見守ってきた開発者や投資家は、自信を持って意見を述べることができない。

私は最近、Moveについて深く調査しました。Solana上でのスマートコントラクト開発の経験もあるため、これらの技術的な概要を説明し、この議論に関心のある人が通常は得られないような深い洞察を共有できる立場にある。

この記事では、Moveの革新的なプログラミングモデル、SuiブロックチェーンとMoveの機能の活用方法、そしてSolanaとそのプログラミングモデルとの比較について、技術的に深く掘り下げていく。

Moveの特徴を強調するために、Solana/RustとSui/Moveを比較してみる。そうする主な理由は、何かを単独で理解しようとするよりも、すでに慣れ親しんでいる別のものと比較した方がはるかに理解しやすいからだ。MoveにはAptos Moveのように、微妙に異なる動きをするものもあることに注意する必要がある。

💡 Move にはいろんな種類の Move があるんですね

この記事のポイントは、異なるMoveのバリエーション間のニュアンスを議論することではなく、Moveの一般的な利点とSolanaプログラミングモデルとの比較を示すことである。そのため、この記事で紹介するMoveの概念(オブジェクトや関連する機能)はSuiのMoveにのみ適用され、他のMoveには適用されない。Sui MoveではないMoveは必ずしもこれらの概念を持っているわけではなく、異なるメカニズム(例えばグローバルストレージ)を使って同じ機能を実現している。しかしそれでも、この記事で説明する主なMoveの利点は、MoveバイトコードをネイティブにサポートするすべてのMove統合に当てはまる。今回Suiを選んだ理由は、単純に私がSuiに精通しているからであり、また記事の形で紹介するのがよち直感的で簡単だと感じたからである。

この記事ではSolanaとSuiの比較をしているが、誰かを誹謗中傷する意図はなく、より理解しやすくするために、これらの技術のさまざまな側面と、利点とトレードオフを強調することである。

2. Solanaのプログラミングモデル

この記事で述べられている点を十分に理解するためには、Solanaのプログラミングモデルについてある程度の知識が必要である。Solanaのプログラミングモデルに馴染みがない方は、Solanaスマートコントラクト・プログラミングに関する私の記事を読むことをお勧めする。

ここでは簡単な復習をしていくが、すでにSolanaのプログラミングモデルに慣れている方は、この章を読み飛ばしても構わない。

Solanaでは、プログラム(スマートコントラクト)は状態を持たず、トランザクションを通じて永続するいかなる状態にも自らアクセス(読み書き)することはできない。状態にアクセスしたり状態を永続化したりするには、プログラムはアカウントを使用する必要がある。各アカウントは一意のアドレス(Ed25519鍵ペアの公開鍵)を持ち、任意のデータを保存できる。

Solanaのアカウント・スペースは、キーがアカウント・アドレス(公開鍵)、値がアカウント・データであるグローバルなキー・バリュー・ストアと考えることができる。そして、プログラムはこのキー・バリュー・ストアの上で、その値を読んだり変更したりすることで操作する。

アカウントには所有権の概念がある。各アカウントは、1つの(そして唯一の)プログラムによって所有される。アカウントがプログラムによって所有されるとき、プログラムはそのデータを変更することが許される。プログラムは所有していないアカウントを変更することは許されないが、それから読み出すことは許される。これらのチェックはランタイム(実行環境)によって動的に行われ、プログラムの実行前と実行後のアカウント状態を比較し、不正な変更が行われた場合にはトランザクションを失敗させる。

各アカウントはまた、アドレスとなる公開鍵に対応する秘密鍵を持っており、この秘密鍵にアクセスできるユーザーは、これを使って取引に署名することができる。例えば、特定の資金にアクセスするために、スマートコントラクトはユーザーに必要な署名を提供するよう要求することができる。

プログラムを呼び出すために、クライアントは呼び出し中にこのプログラムがアクセスするアカウントを指定する必要がある。これは、トランザクション処理のランタイムが、データの一貫性を保証しながら、重複しないトランザクションを並行して実行するようにスケジュールできるようにするためである。これは、高いスループット(処理能力)を可能にするSolanaの設計上の特徴の一つである。

プログラムはCPIコールを介して他のプログラムを呼び出すことができる。これらの呼び出しは、クライアント側からの呼び出しとほぼ同じように動作する。呼び出し側プログラムは、呼び出されるプログラムがアクセスするアカウントを指定する必要があり、呼び出されるプログラムは、クライアントから呼び出された場合と同じ入力チェックをすべて行う(呼び出し側プログラムを信頼しない)。

💡 CPIは、Cross-Program Invocation の略で、プログラム間呼び出しといいます。あるプログラムから別のプログラムへの直接呼び出しで、Solanaプログラムの構成可能性を高めることができます。クライアントが JSON RPC を使用して任意のプログラムを呼び出すことができるように、任意のプログラムが CPI を介して他のプログラムを呼び出すことができます。CPI は基本的に、Solana エコシステム全体を開発者が自由に使える1つの巨大なAPIに変えます。

Solana Cookbook

PDAアカウントは特別な種類のアカウントであり、プログラムが秘密鍵を所有または保存することなくアカウント署名を提供できるようにする。PDAは、PDAが生成されたプログラムだけがそのプログラムに対する署名を作成できることを保証する(他のユーザーやプログラムは作成できない)。これは、プログラムがCPIコールを介して他のプログラムとやり取りし、権限を提供する必要がある場合(例:金庫の実装)に役に立つ。PDAは、プログラム以外の誰もがプログラムのリソースに直接アクセスできないことを保証する。PDAはまた、決定論的アドレスでのアカウント作成にも使用できる。

💡 PDAは、Program Derived Addresses の略で、プログラム派生アドレスといいます。PDAについてはユウキさんのnoteが参考になります
【Solanaコアコンセプト⑤】 プログラム派生アドレス

以上が、Solana上でのセキュアなスマートコントラクト・プログラミングの基本的な構成要素だ。繰り返しになるが、これらの概念のどれかが不明瞭だと感じたら、Solanaスマートコントラクトプログラミングに関する私の記事を読むことを強くお勧めする。

ある意味で、Solanaのプログラムをオペレーティング・システムのプログラムと考え、アカウントをファイルと考えることができる。誰でも自由に任意のプログラムを実行したり、デプロイすることもできる。プログラム(スマートコントラクト)が実行されると、ファイル(アカウント)からの読み込みとファイル(アカウント)への書き込みが行われる。すべてのファイルはすべてのプログラムが読むことができるが、ファイルの所有権を持つプログラムだけが書き込むことができる。プログラムは他のプログラムを実行することもできるが、互いに信頼し合うことはない。誰がプログラムを実行したとしても、その入力は潜在的に敵対的なものであると想定する必要がある。このOSは誰でもグローバルにアクセスできるので、ユーザーの権限と所有権の機能を有効にするために、プログラムにネイティブの署名検証サポートが追加されている......完璧な例えではないが、面白いものである。

3. Moveのプログラミングモデル

Moveでは、スマートコントラクトはモジュールとして公開される。モジュールは関数とカスタム型(構造体)で構成される。構造体は、プリミティブ型(u8、u64、boolなど)または他の構造体であるフィールドで構成される。関数は他の関数を呼び出すことができます。 同じモジュール内のものであればもちろん、公開されている場合は他のモジュールの関数も呼び出せる。

これをSolanaの文脈で言うと、すべてのスマートコントラクトが単一のプログラム内のモジュールとして公開されているようなものだ。これは、すべてのスマートコントラクト(モジュール)が同じ型システムの中に含まれ、中間APIやインターフェースを介さずにお互いを直接呼び出すことができることを意味する。これは非常に重要なことであり、その意味するところはこの記事を通して徹底的に議論されるだろう。

3.1. オブジェクト

話を続ける前に、次に述べるオブジェクトの概念はSui Move特有のものであり、Moveの他の種類(AptosやDiem/core Move)では異なる可能性があることに気に留めておくべきである。それでも、他のMoveでは同じこと(状態の永続化)を実現する似たようなソリューションがある。ここでSuiのオブジェクトを紹介する主な理由は、この記事の後半で紹介するコードサンプルがSui Moveに基づいているため、そしてオブジェクトのほうがcore Moveのグローバルストレージ・メカニズムなどよりも直感的に理解しやすいからだ。しかし重要なのは、この記事で説明するMoveの主な利点はすべて、Aptosを含むMoveバイトコードをネイティブにサポートしているMoveに適用されるということだ。SuiとAptosがどのように異なるかを知るには、Sui Moveを作成した理由の記事Aptos Moveのドキュメントが参考になる。

オブジェクトは構造体のインスタンスで、ランタイムによって保存される。また、トランザクションをまたいで状態を永続化する。

Suiには3種類のオブジェクトがある:

  • 所有オブジェクト

  • 共有オブジェクト

  • 不変オブジェクト

所有オブジェクト
ユーザーに属するオブジェクトです。オブジェクトを所有するユーザーだけがトランザクションでそのオブジェクトを使用できる。所有権のメタデータは完全に透明であり、ランタイムによって処理される。これは公開鍵暗号を使用して実装されており、所有オブジェクトは公開鍵(ランタイム内のオブジェクトのメタデータに格納されている)に関連付けられており、トランザクションでオブジェクトを使用したい場合は常に対応する署名を提供する必要があります。

💡 普段みんながミントしているNFTはこの所有オブジェクトに当てはまります

共有オブジェクト
所有オブジェクトに似ているが、所有者を持たない。そのため、トランザクションで使用するときに秘密鍵を持っている必要はなく、誰でも使用できる。任意の所有オブジェクトはその所有者にとって共有オブジェクトにすることができる。一度共有されたオブジェクトは、永久に共有されたままとなるので、転送したり所有オブジェクトになることはない。

💡 流動性プールのオブジェクトは共有オブジェクトであることが多いです

不変オブジェクト
変更できないオブジェクトのこと。一度オブジェクトが不変とマークされると、そのオブジェクトのフィールドは二度と変更することはできない。共有オブジェクトと同様、所有者を持たず、誰でも使うことができる。

💡 設計しだいですが、設定情報などは不変オブジェクトにしたりすることもあります

Moveのプログラミングモデルは非常に直感的でシンプルだ。各スマートコントラクトはモジュールであり、関数と構造体の定義で構成されている。構造体は関数内でインスタンス化され、関数呼び出しを通じて他のモジュールに渡すことができる。トランザクションを越えて構造体を持続させるために、Suiは構造体をオブジェクト(所有、共有、不変)に変換する。これはSui特有のもので、他のMoveでは少し異なる。オブジェクトについては以上だ!


1~3章終わり


次の章は以下から


この記事が気に入ったらサポートをしてみませんか?