10月18日のAptosネットワークのメインネットローンチに伴い、Moveプログラミング言語とそのエコシステムは影響力を増し続けています。コミュニティの皆様にご参加いただくため、Moveにおける安全な開発プラクティスを提供する一連の記事を公開します。例、説明、そして最も重要なセキュリティプラクティスを通じて、皆様をMoveの世界へご案内します。
TL;DR
この記事では、以下の内容を説明します。
- Aptosアプリケーションの作成と開発方法
- モジュール(Moveにおけるスマートコントラクト)の構造
- ローカルネットワークでモジュールをコンパイルして公開する方法
- ブラウザでモジュールとやり取りし、発生したイベントを確認する方法
0x1. Moveとそのエコシステムについて
Moveは、スマートコントラクト開発のために設計されたDiem(2020年12月以前の名称はLibra)から派生したものです。安全で高速、柔軟であると謳われており、次世代言語になることを目指しています。しかし、AptosやSuiのような新しく登場したプロジェクトは、元のMoveを直接採用するのではなく、ニーズに合わせていくつかの変更を加えています。
特に明記されていない限り、ここではAptosのコンテキストでの開発プラクティスに焦点を当てます。これらのアイデアは、他のMoveベースのプロジェクトにも一般的に適用できるからです。また、Moveプログラミング言語の基本的な理解のために、すでにMoveBookを読了されていることを前提とします。
0x2. 環境の準備
0x2.1 Aptos Toolchain
AptosはすでにCLIにMoveを統合しています。そのため、CLIのインストールに従って対応するツールチェーンをインストールすることをお勧めします。インストールが完了したら、ターミナルでaptosと入力し、以下の出力が表示されるはずです。
$ aptos
aptos 1.0.1
Aptos Labs <[email protected]>
Command Line Interface (CLI) for developing and interacting with the Aptos blockchain
USAGE:
aptos <SUBCOMMAND>
OPTIONS:
-h, --help Print help information
-V, --version Print version information
SUBCOMMANDS:
account Tool for interacting with accounts
config Tool for interacting with configuration of the Aptos CLI tool
genesis Tool for setting up an Aptos chain Genesis transaction
governance Tool for on-chain governance
help Print this message or the help of the given subcommand(s)
info Show build information about the CLI
init Tool to initialize current directory for the aptos tool
key Tool for generating, inspecting, and interacting with keys
move Tool for Move related operations
node Tool for operations related to nodes
stake Tool for manipulating stake and stake pools
0x2.2 ローカルテストネットとアカウント
Aptosは、開発とデプロイのためにいくつかのネットワーク(メインネット、テストネット、デブネット、ローカルテストネット)を提供しています。この記事では、ローカルテストネットを使用します。
ローカルテストネットを起動するには、次のコマンドを入力します。
$ aptos node run-local-testnet --with-faucet --force-restart
以下のような出力が表示されるはずです。
......
Aptos is running, press ctrl-c to exit
Faucet is running. Faucet endpoint: 0.0.0.0:8081
次に、次のコマンドを入力してアカウントを作成します(前のターミナルウィンドウをフォアグラウンドで維持したい場合は、別のターミナルウィンドウで行うと良いでしょう)。
$ aptos init
このコマンドはインタラクティブなシェルを起動し、いくつかのプロパティを指定する必要があります。ここではlocalネットワークを選択します。その後、現在のディレクトリに.aptosフォルダが作成され、デフォルトのアカウント設定が保存されます。ファイルを確認し、ご自身のアカウントアドレス(例:c0d8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx14bd)をコピーしてください。
ヒント#1: アカウント設定ファイルは安全に保管してください!秘密鍵がそこに書き込まれています!
0x3. 最初のHello Worldプログラム
Hello Worldプログラムは、コーディング学習の最初のステップとして常に使用されます。この慣例に従って、Moveアプリケーションを開発する方法を説明します。
0x3.1 パッケージの準備
好きなディレクトリを選択し、次のコマンドを入力します。
$ aptos move init --framework-local-dir "../../aptos-core/aptos-move/framework/aptos-framework" --name hello
このコマンドは、指定された場所(開発ワークスペース)に新しいMoveパッケージを作成します。Aptosフレームワークの一部のライブラリ関数が必要なため、Aptosフレームワークのローカルディレクトリを指定しています(別の場所の場合は相対パスを変更する必要がある場合があります)。Alternatively、--framework-git-revを使用してAptosフレームワークのgitリビジョンまたはブランチを指定することもできます。
これで、ディレクトリ内にMove.tomlファイルが表示されます。このファイルには、依存関係の設定だけでなく、パッケージ名とバージョンも記述されています。さらに、Moveソースコードを格納するためのsourcesという名前のフォルダも存在します。sourcesディレクトリに.moveファイルを作成すると、ワークスペースの準備が整います。
[package]
name = 'hello'
version = '1.0.0'
[dependencies.AptosFramework]
local = '../../aptos-core/aptos-move/framework/aptos-framework'
[addresses]
BlockSec="c0d8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx14bd"
Move.tomlの最後の行では、先ほど作成したアカウントアドレスをBlockSecに関連付けます。これは、このパッケージのモジュール(スマートコントラクト)を公開するために使用されます(後述)。上記の実際のアドレスはプレースホルダーであり、ご自身のアカウントアドレスに必ず置き換えてください。
0x3.2 モジュールの準備
以下は、シンプルで完全なサンプルモジュールです。これはMoveファイル(例:hello.move)に直接配置できます。以下では、コードを詳しく見て、Moveと他のプログラミング言語との違いを説明します。もしそれらに非常に慣れている場合は、このセクションをスキップしても構いません。
module BlockSec::hello{
use aptos_framework::account;
use aptos_framework::event;
use std::signer;
use std::string::{String, utf8};
struct SecEventStore has key{
event_handle: event::EventHandle<String>,
}
public entry fun say_hello_script(account: &signer) acquires SecEventStore{
say_hello(account);
}
public fun say_hello(account: &signer) acquires SecEventStore{
let address_ = signer::address_of(account);
if(!exists<SecEventStore>(address_)){
move_to(account, SecEventStore{event_handle: account::new_event_handle(account)});
};
event::emit_event<String>(&mut borrow_global_mut<SecEventStore>(address_).event_handle, utf8(b"Hello World!"));
}
}
ここでは、BlockSecアドレスに公開されるhelloという名前のモジュールを定義します。このモジュールのエントリー関数はsay_hello_scriptという名前で、say_function関数を呼び出します。このモジュールは、"Hello World!"メッセージを持つイベントを発行するために使用されていることは容易に理解できます(say_hello関数内)。ただし、まだ明確に説明する必要がある詳細がいくつかあります。
具体的には、aptos_framework名前空間のevent::emit_event関数を使用するには、event::EventHandle構造体が必要です。なぜなら、emit_event関数は以下の宣言を持っているからです。
/// Emit an event with payload `msg` by using `handle_ref`'s key and counter.
public fun emit_event<T: drop + store>(handle_ref: &mut EventHandle<T>, msg: T)
struct EventHandle<phantom T: drop + store> has store {
/// Total number of events emitted to this event stream.
counter: u64,
/// A globally unique ID for this event stream.
guid: GUID,
}
EventHandleはkeyアビリティを持たないことに注意してください。これは、別の構造体に格納する必要があることを意味します。したがって、EventHandleを格納するためにSecEventStoreという名前の新しい構造体を定義します。
struct SecEventStore has key{
event_handle: event::EventHandle<String>,
}
ヒント#2: Moveでは構造体のアビリティを考慮する必要があります。
keyアビリティのみがmove_toできることを忘れないでください。storeアビリティのみを持つ構造体をモジュールが返し、グローバルストレージに保持したい場合は、新しい構造体をラッパーとして定義することを検討してください。
簡単にするために、メッセージを表すためにStringを使用します。したがって、say_hello関数の最後のステップは次のようになります。
event::emit_event<String>(&mut borrow_global_mut<SecEventStore>(address_).event_handle, utf8(b"Hello World!"));
ヒント#3: Moveは
String型をネイティブにサポートしていません。標準ライブラリは、バイトベクターをStringに送信する機能を提供します。詳細については、GitHubリポジトリのソースコードを確認してください。
すべての新規ユーザーがSecEventStoreに登録するようにするには、まずexists関数を通じてユーザーアカウントに構造体が存在するかどうかを確認する必要があります。ユーザーがリソースを持っていない場合、関数は1つ作成し、ユーザーアカウントに移動します。
if(!exists<SecEventStore>(address_)){
move_to(account, SecEventStore{event_handle: account::new_event_handle(account)});
};
0x3.3 モジュールのコンパイルと公開
モジュールが準備できたら、次のコマンドでコンパイルできます。
$ aptos move compile
Compiling, may take a little while to download git dependencies...
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING hello
{
"Result": [
"c0d8xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx14bd::hello"
]
}
必要であればテストすることもできます。
$ aptos move test
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING hello
Running Move unit tests
Test result: OK. Total tests: 0; passed: 0; failed: 0
{
"Result": "Success"
}
これで、Aptosネットワークにモジュールをデプロイできます。ユーザーは自身が管理するアカウントにのみモジュールを公開できるため、BlockSecとアカウントを関連付けたことを思い出してください。さらに、ファウセットはガス料金を支払うためにアカウントにAPTを供給しています。残りは、MoveパッケージのモジュールをAptosネットワークに公開することだけです。以下のように行います。
$ aptos move publish --package-dir ./ --profile default
Compiling, may take a little while to download git dependencies...
INCLUDING DEPENDENCY AptosFramework
INCLUDING DEPENDENCY AptosStdlib
INCLUDING DEPENDENCY MoveStdlib
BUILDING hello
package size 1271 bytes
Do you want to submit a transaction for a range of [672200 - 1008300] Octas at a gas unit price of 100 Octas? [yes/no] >
yes
{
"Result":
...
}
これもインタラクティブなシェルであり、Resultの内容は省略されています。
0x3.4 モジュールとのやり取り
モジュールにイベントを発行させるには、次のコマンドを入力します。
$ aptos move run --function-id default::hello::say_hello_script
Do you want to submit a transaction for a range of [34500 - 51700] Octas at a gas unit price of 100 Octas? [yes/no] >
yes
{
"Result": {
"transaction_hash": "0x9af16532de5e79803c823fe28e3251703927d93809274b76972d8e83c6fcd433",
...
}
}
エントリー関数として、say_hello_script関数は直接呼び出すことができます。スクリプトを作成して、スクリプト内でsay_hello関数を呼び出すこともできます。
ヒント#4: より良いやり取り体験のために、エントリー関数を定義することは良いプラクティスです。ユーザーがプロジェクトとやり取りするためのスクリプトを開発することもできます。
従来のWeb2のHello Worldプログラムとは異なり、発行されたイベントはシェルには表示されません。Aptos Explorerを確認し、localネットワークを選択してください。

次に、シェルからtransaction_hashの値をコピーして検索バーに貼り付け、トランザクションの詳細を確認してください。

最後に、Eventsをクリックすると、Aptosネットワークがあなたに挨拶してくれるでしょう。

0x4. 次は何?
Hello Worldプログラムは、Moveアプリケーション開発におけるほんの小さな一歩に過ぎません。今後の記事シリーズでは、Aptosで安全でセキュアなMoveアプリケーションを開発する方法について、さらに詳しくご紹介します。続報にご期待ください!
BlockSecについて
BlockSecは、世界的に著名なセキュリティ専門家グループによって2021年に設立された、先駆的なブロックチェーンセキュリティ企業です。当社は、Web3の世界のセキュリティとユーザビリティを向上させ、その大量採用を促進することに尽力しています。そのために、BlockSecはスマートコントラクトとEVMチェーンのセキュリティ監査サービス、セキュリティ開発と脅威のプロアクティブなブロックのためのPhalconプラットフォーム、資金追跡と調査のためのMetaSleuthプラットフォーム、そしてWeb3ビルダーが暗号通貨の世界を効率的にサーフィンするためのMetaSuites拡張機能を提供しています。
これまでに、MetaMask、Uniswap Foundation、Compound、Forta、PancakeSwapなどの300を超える著名なクライアントにサービスを提供し、Matrix Partners、Vitalbridge Capital、Fenbushi Capitalなどの著名な投資家から2回の資金調達で数千万米ドルを獲得しました。
公式ウェブサイト: https://blocksec.com/
公式Twitterアカウント: https://twitter.com/BlockSecTeam



