メインコンテンツへスキップ

Aleo上でLeoプログラムを構築・デプロイする方法

更新日:
2026年5月21日

読了時間:9分

概要

入門ガイドでは、Aleoのアーキテクチャについて、オフチェーン実行、オンチェーン検証、プライベート状態としてのレコードについて解説しました。このガイドでは、それらを実践します。Leoでプライベートトークンを記述し、テストを行い、Quicknodeのエンドポイントを通じてAleoテストネットにデプロイします。

私たちが開発しているトークンは、意図的にシンプルに設計されています。機能は2つだけで、パブリックな状態変数はありません。トークンは暗号化されたレコードとして発行され、非公開で転送されます。ネットワークはゼロ知識証明を用いてすべての取引を検証しますが、誰がトークンを送信したか、誰が受け取ったか、あるいはどのくらいの量が移動したかについては一切把握しません。これがAleoの最大の売りであり、私たちがここで目指しているものです。


要約
  • 2つの機能を持つプライベートトークンを構築します: mint_private そして transfer_private
  • すべてのステートは暗号化されたレコード内に格納されているため、オンチェーン上には何も表示されません
  • すべてのコードはLeo 4.0の構文を使用しています: fn 関数については、 記録 プライベートな状態型の場合
  • Quicknodeのエンドポイントを通じて、Aleoテストネットにデプロイするには、 leo deploy --broadcast

学習内容

  • 完全に非公開の状態を保持するためにレコードを使用したLeoプログラムの書き方
  • テスト方法 @test 注釈および レオテスト
  • Aleoテストネットへのデプロイ方法(以下を通じて) leo deploy
  • プライベートな取引を実行する方法と、オンチェーン上で何が可視化されるか(何も表示されない)を理解する方法

必要なもの

  • AleoとLeo入門』ガイドで解説されている概念について理解していること
  • Rust 1.94.1 以降(Leo ではこのバージョンが必要です。実行してください rustupの更新 (必要に応じてアップグレードしてください)
  • Aleoテストネットのエンドポイントを備えたQuicknodeアカウント
  • Aleoファウセットから獲得したテストネットALEOクレジット
  • 端末へのアクセス

Quicknodeエンドポイントを作成する

Aleoネットワーク上でプログラムを展開したり、プログラムとやり取りしたりするには、Aleo RPCエンドポイントへのアクセスが必要です。独自のノードを運用することも可能ですが、Quicknodeがインフラストラクチャを管理してくれるため、その手間はかかりません。

まだQuicknodeアカウントをお持ちでない場合は、アカウントを作成してください。ログイン後、「エンドポイントを作成」をクリックし、AleoチェーンとTestnetネットワークを選択してください。

Quicknode Aleo エンドポイント

エンドポイントを作成したら、HTTP プロバイダーの URL をコピーしてください。この URL は、後でプロジェクトの設定に追加することになります。

追加 /v2 QuicknodeエンドポイントURLの末尾に。Leoはネットワークパスを付加します(/testnet/...) をAPI呼び出し時に自動的に指定する必要があり、QuicknodeのAleoエンドポイントでは /v2 接頭辞。

開発環境のセットアップ

cargo を使って Leo コンパイラをインストールします:

cargo install leo-lang

インストールを確認してください:

leo --version

新しいプロジェクトの骨組みを作成する:

leo new private_token
cd private_token

これにより、次のようなプロジェクト構造が作成されます:

ファイル/ディレクトリ目的
src/main.leoプログラムのソースコード
tests/以下のテストファイルで @test 注釈付き関数
program.jsonプロジェクトのメタデータ:プログラム名、バージョン、依存関係

また、以下のものも必要になります。 .env デプロイ設定用のファイル。プロジェクトのルートディレクトリに作成してください:

警告

追加 .env あなたの .gitignore. 秘密鍵をバージョン管理システムに絶対に登録しないでください。

touch .env

以下を追加してください:

NETWORK=testnet
PRIVATE_KEY=APrivateKey1zkp... # generate one with: leo account new
ENDPOINT=https://your-quicknode-aleo-endpoint.quiknode.pro/your-auth-token/v2

まだ秘密鍵をお持ちでない場合は、以下のコマンドで生成してください。 leoアカウント(新規) それを貼り付けてください。エンドポイントには、先ほどコピーしておいたQuicknodeのURLを、 /v2 添付しました。

トークンプログラムの作成

私たちはプライベートトークンを構築しています。残高を記録した公開台帳も、誰でも閲覧できるオンチェーン上のマッピングも存在しません。すべてのトークンは、所有者だけが閲覧できる暗号化された記録として存在します。誰かがトークンを転送すると、古い記録は破棄され、新しい記録が作成されますが、そのすべてがオフチェーンで行われます。ネットワークが認識するのは、ルールが遵守されたという証明のみです。

2つの関数がすべてを処理します:

  • mint_private 暗号化されたレコードとして新しいトークンを作成します
  • transfer_private トークンをあるアドレスから別のアドレスへ、非公開で移動させる

のコンテンツを置き換えてください src/main.leo 出演:

program private_token.aleo {

record Token {
owner: address,
amount: u64,
}

fn mint_private(receiver: address, amount: u64) -> Token {
return Token {
owner: receiver,
amount: amount,
};
}

fn transfer_private(sender: Token, receiver: address, amount: u64) -> (Token, Token) {
let difference: u64 = sender.amount - amount;

let remaining: Token = Token {
owner: sender.owner,
amount: difference,
};

let transferred: Token = Token {
owner: receiver,
amount: amount,
};

return (remaining, transferred);
}

@noupgrade
constructor() {}
}

ここにある内容を順を追って見ていきましょう:

トークンの記録 プライベートな状態を定義します。各トークンは、台帳上の暗号化されたレコードであり、 所有者 そして、 金額。所有者のビューキーでのみ復号化できます。公開されている残高テーブルは存在しません。

mint_private 新しいものを生成します トークン 記録。これは完全にオフチェーンで実行されます。ネットワークは証明を検証しますが、受取人や金額を一切確認することはありません。

transfer_private 既存の トークン レコードを読み取り、それを消費して、2つの新しいレコードを生成します。1つは送金先向けの、送金金額が記載されたレコード、もう1つは送金元向けの、残高が記載されたレコードです。これはビットコインのUTXOモデルの仕組みと似ていますが、すべてが暗号化されている点が異なります。Leoの整数はアンダーフロー時にラップオーバーしないため、明示的な残高チェックは行われません。もし sender.amount - amount 負の値になると、そのトランザクションは自動的に失敗します。

@noupgrade その @noupgrade このアノテーションはプログラムをロックし、デプロイ後に変更できないようにします。アップグレード可能なプログラムの場合は、代わりに認証ロジックを含むコンストラクタを記述し、 Leoのアップグレード 新しいバージョンを公開する

constructor() {} - すべてのAleoプログラムにはコンストラクタが必要です。

プログラムのテスト

Leo には組み込みのテストフレームワークが備わっています。テスト関数は tests/ ディレクトリに移動し、 @test 注釈。テストファイルはそれ自体がLeoプログラムであるため、 プログラム ブロックと、そして インポート テスト対象のプログラムについて。

既存のファイルを開く tests/test_private_token.leo そして、その内容を次のように置き換えてください:

import private_token.aleo;

program test_private_token.aleo {

@test
fn test_mint_private() {
let receiver: address = aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc;
let result: private_token.aleo::Token = private_token.aleo::mint_private(receiver, 100u64);
assert_eq(result.owner, receiver);
assert_eq(result.amount, 100u64);
}

@test
fn test_transfer_private() {
let alice: address = self.signer;
let bob: address = aleo1qgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqanmpl0;

let minted: private_token.aleo::Token = private_token.aleo::mint_private(alice, 100u64);
let (remaining, transferred): (private_token.aleo::Token, private_token.aleo::Token) = private_token.aleo::transfer_private(minted, bob, 30u64);

assert_eq(transferred.owner, bob);
assert_eq(transferred.amount, 30u64);
assert_eq(remaining.owner, alice);
assert_eq(remaining.amount, 70u64);
}

@test
@should_fail
fn test_transfer_more_than_balance() {
let alice: address = aleo1qqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqq3ljyzc;
let bob: address = aleo1qgqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqqanmpl0;

let minted: private_token.aleo::Token = private_token.aleo::mint_private(alice, 50u64);
// This should fail: transferring 100 from a record with only 50
let (remaining, transferred): (private_token.aleo::Token, private_token.aleo::Token) = private_token.aleo::transfer_private(minted, bob, 100u64);
}

@noupgrade
constructor() {}
}

テストを実行します:

レオテスト

3つのテストが合格したことを示すLeoのテスト出力

テストファイルについて、いくつか注意すべき点があります:

  • import private_token.aleo; メインプログラムをスコープ内に取り込む
  • 型と関数では、フルパスを使用します: private_token.aleo::Token, private_token.aleo::mint_private()
  • In test_transfer_private, ここでは 自己署名型 VMでは、入力レコードがトランザクションの署名者に属している必要があるため、これをミントアドレスとして指定します
  • @should_fail レオに、このテストは失敗すると予想されることを伝えます。もし関数がエラーなしで完了した場合、テスト自体は失敗となります
  • すべてのプログラム(テストプログラムを含む)にはコンストラクタが必要です。ここでは、 @noupgrade ここでは、シンプルにするために

テスト名を基準にフィルタリングすることができます:

leo test mint

これにより、名前に「mint」が含まれるテストのみが実行されます。

Aleoテストネットへのデプロイ

プログラムのコンパイルが完了し、テストも合格したので、いよいよデプロイする段階です。

テストネットのクレジットを入手する

Aleoのファウセットにアクセスし、ご自身のアカウントアドレスに対してテストネットクレジットを申請してください。

Aleoのアドレスを確認する方法

実行 Leoアカウントのインポート あなたの .env:

leo account import APrivateKey1zkp...

これにより、アドレス、ビューキー、および秘密鍵が表示されます。アドレスをコピーしてください。

プログラム名を選択してください

プログラム名は、ネットワーク全体で一意である必要があります。もし private_token.aleo すでに使用されている場合は、両方の名前を更新してください src/main.leo そして program.json. 10文字未満の名前には、短いドメイン名の料金が高くなるのと同様に、名前が短くなるほど高くなるネームスペース料金がかかります。10文字以上の名前には、ネームスペース料金はかかりません。

デプロイ

leo deploy --broadcast

レオは、確認を求める前に、料金の内訳を表示します:

手数料の内訳対象範囲
ストレージプログラムデータの1バイトにつき1ミリクレジット
総説回路の複雑さに比例して(変数の数 + 制約の数)
名前空間10文字未満のプログラム名には追加料金がかかります(10文字以上の場合は0)
優先順位インクルードを高速化するためのオプション設定(デフォルトは 0)

確認後、Leoはデプロイメントトランザクションをブロードキャストし、ネットワークを最大12ブロックにわたって監視して、そのトランザクションがブロックに組み込まれたことを確認します。

手数料の内訳と確認情報を表示するLeoのデプロイ出力

Aleo Explorer でデプロイ状況を確認できます。

非公開取引の実行

プログラムのデプロイが完了したので、実際に使ってみましょう。以下の各手順は、お使いのマシン上でオフチェーンで実行され、ネットワーク側には証明のみが送信されます。

ミント・トークン

leo execute mint_private <RECEIVER_ADDRESS> 1000u64 --broadcast

置換 <RECEIVER_ADDRESS> Aleoのアドレスを指定して。これにより、 トークン 受信者向けに暗号化された記録。取引はブロックチェーン上に記録されますが、記録の内容(所有者、金額)は暗号化されています。ブロックチェーンを監視している者であっても、何が発行されたのか、あるいは誰に発行されたのかを知ることはできません。

Leoは実行後に出力レコードを出力します。その内容は次のようになります:

{
owner: aleo1abc...def.private,
amount: 1000u64.private,
_nonce: 6068899261705353026606683251009719039686976057706338283793929594435531277185group.public,
_version: 1u8.public
}

その 所有者 そして 金額 フィールドにはマークが付いています .private、つまり、それらは台帳上で暗号化されているということです。完全な記録を保存しておいてください。これを transfer_private.

トークンの転送

leo execute transfer_private "{ owner: aleo1abc...def.private, amount: 1000u64.private, _nonce: 6068...185group.public, _version: 1u8.public }" <RECEIVER_ADDRESS> 300u64 --broadcast

そのレコードを、mintステップからの出力全体を引用符で囲んだものに置き換えてください。全体を { owner: ..., amount: ..., _nonce: ..., _version: ... } block は単一の引数です。これにより、既存のリコードが消費され、2つの新しいリコードが作成されます。受信者用に300トークン、あなた(更新後の金額)用に700トークンです。

ネットワークが認識するのは、有効な証明だけです。それだけです。送信者アドレスも、受信者アドレスも、金額もありません。バリデーターは、その計算が何を意味するのかを知ることなく、計算が正しいことを確認するのです。

オンチェーン上で何が確認できるか

これこそが、この一連の作業の要点です。転送完了後、ターミナル上では次のように表示されます:

2つの出力レコードとトランザクションIDが表示されたCLIの出力

ターミナルには、2件の出力レコード(受信者への300トークン、自分への700トークン)とトランザクションIDが表示されます。何が起きたのかが正確にわかります。

そのトランザクションIDを使って、Aleo Explorerで検索してみてください。「概要」タブでは、そのトランザクションがオンチェーンに反映されたことが確認できます:

トランザクションIDが表示されたAleo Explorerの「概要」タブ

トランザクションIDは同じで、ネットワーク上でも確認済みです。しかし、「トランザクション」タブをクリックしてみてください:

暗号化された入力と出力が表示されたAleo Explorerの「取引」タブ

入出金は暗号化されています。送信者も受信者も、金額も一切明かされません。バリデーターたちは、送金の内容を知ることなく、そのプルーフが有効であることを確認しました。

これに対し、標準的なEVMトークンの送金では、送信者、受信者、金額、および取引履歴の全記録が誰でも閲覧可能です。

結論

当初は何もなかったプロジェクトでしたが、今ではAleoテストネット上にプライベートトークンがデプロイされるまでになりました。このプログラムには2つの機能があります: mint_private トークンを作成し、 transfer_private それらを移動させます。すべての状態は暗号化されたレコード内に格納されています。トークンの残高や送金履歴に関する情報は、オンチェーン上では一切確認できません。

これはごく簡単な例ですが、基本的なパターンを示しています。プロダクショントークンでは、マッピングなどを使用して、各パブリック残高を合計することになります。 最終 ブロック)、パブリックとプライベート間を移行するための変換関数、および鋳造に関するアクセス制御。この 入門ガイド さらに機能を拡張したい場合、マッピングやファイナルブロックの仕組みについて解説しています。

プログラム間の呼び出し、複合フューチャー、およびより高度なパターンについては、『Aleo 開発者向けドキュメント』およびleo-examplesリポジトリを参照してください。

よくある質問

AleoでLeoプログラムを展開するには、どれくらいの費用がかかりますか?

デプロイメント料金には、プログラムデータの1バイトあたり1ミリクレジットのストレージ費用、回路の複雑度(変数数と制約数に基づく)に比例する合成費用、および10文字未満のプログラム名に対するネームスペース料金の3つの要素があります。優先度料金は任意であり、デフォルトでは0に設定されています。Leo CLIでは、デプロイメントを確定する前に、費用の内訳をすべて確認することができます。

「leo run」と「leo execute」の違いは何ですか?

`leo run` は、証明を生成せずに、関数をローカルでコンパイルして実行します。これは、開発中の迅速なテストに役立ちます。`leo execute` も同様にローカルで実行しますが、さらに回路を合成し、zk-SNARK 証明を生成します。これは、デプロイやオンチェーン実行に必要な処理です。

Aleoにデプロイ済みのLeoプログラムを更新することはできますか?

はい、プログラムがアップグレード可能な状態でデプロイされている場合、`leo upgrade` コマンドを使用して新しいバージョンをデプロイすることができます。このアップグレードでは、プログラム名とアドレスはそのままに、オンチェーン上のプログラムのバイトコードが置き換えられます。

ブロックエクスプローラーでトークンの残高が表示されないのはなぜですか?

プライベートトークンでは、パブリックマッピングではなくレコードが使用されます。レコードは台帳上で暗号化されており、所有者だけが自身のビューキーを使って復号化できます。ブロックエクスプローラーはパブリックな状態(マッピング)しか表示できないため、プライベートトークンの残高はブロックエクスプローラーからは見えません。自分のレコードは、Leo CLIを通じてローカルでしか確認できません。

皆様からのフィードバックを心よりお待ちしております!❤️

ご意見や新しいトピックに関するご要望などがありましたら、ぜひお知らせください。皆様からのご連絡を心よりお待ちしております。

このガイドをシェアする