ICP Rust CDK学習メモ
  • ICP Rust CDK学習メモ
  • ⚙️開発環境準備
  • 開発
    • テンプレート生成 (dfx new)
    • Frontend開発
      • 1. シンプルなHTML
      • 2. Canister呼び出し
    • Backend開発
      • 1. Hello
      • 2. データ更新/参照
      • 3. ic_cdk::caller()
      • 4. ic_cdk::call()
      • 5. 動的画像生成
      • 6. staticファイル参照
      • 7. HTTPS outcalls
      • 8. Threshold ECDSA
    • Bootcamp
      • Calculator ➕✖️➖➗
      • Homework diary 📔
      • Student wall 🎨
      • MotoCoin 🪙
      • The Verifier 👨‍🏫
      • The Dapp 🚀
  • サンプル
    • 📔Diary
  • 技術情報
    • 🪪Principal
    • 🪪Internet Identity
    • 🪙Token
    • 🖼️NFT
    • 🗝️VetKey
  • ツール
    • dfx
      • dfx identity
    • quill
  • 参考情報
    • 🔗リンク集
GitBook提供
このページ内
  • 1. Rustプロジェクト作成
  • 2. Cargo.tomlの編集
  • (1) IC関連ライブラリ追加
  • (2) crate-type設定
  • 3. dfx.jsonの作成
  • 4. candidの作成
  • 5. lib.rsの編集
  • 6. Unitテスト
  • 7. Local Canisterの起動
  • 8. Local Canisterへの配備

役に立ちましたか?

GitHubで編集
  1. 開発
  2. Bootcamp

Homework diary 📔

前へCalculator ➕✖️➖➗次へStudent wall 🎨

最終更新 1 年前

役に立ちましたか?

2023年5月に開催されたのプロジェクトをRust言語で実装します。

1. Rustプロジェクト作成

Rustのプロジェクト「day2」を作成します。cargo newコマンドを--libオプションを付与して実行します。

$ cargo new day2 --lib
$ cd day2

生成されたファイルは以下の通りです。

day2
├── Cargo.toml
└── src
    └── lib.rs

2. Cargo.tomlの編集

(1) IC関連ライブラリ追加

ライブラリを使用します。最新バージョンでよいかと思いますので、以下のように実行ます。

$ cargo add candid ic-cdk serde

candid、serdeは、CandidType, Deserialize指定に必要?

(2) crate-type設定

Canister上から関数が正しく呼び出させるようcrate-typeをcdylibにします。

[lib]
crate-type = ["cdylib"]

3. dfx.jsonの作成

Canisterの定義を行います。

{
  "canisters": {
    "day2": {
      "candid": "./day2.did",
      "package": "day2",
      "type": "rust"
    }
  },
  "defaults": {
    "build": {
      "args": "",
      "packtool": ""
    }
  },
  "version": 1
}

4. candidの作成

dfx.jsonの [canisters] > [day2] > [candid]項目に指定したファイルに、Canisterに配置するDappが提供する関数のI/Fを定義します。

type Time = int;
type Homework = record {
    "title": text;
    "description": text;
    "dueDate": Time;
    "completed": bool;
};

type ResultHomework = variant { Ok: Homework; Err: text };
type ResultOnly = variant { Ok; Err: text };

service: {
    addHomework: (Homework) -> (nat);
    getHomework: (nat) -> (ResultHomework) query;
    updateHomework: (nat, Homework) -> (ResultOnly);
    markAsCompleted: (nat) -> (ResultOnly);
    deleteHomework: (nat) -> (ResultOnly);
    getAllHomework: () -> (vec Homework) query;
    getPendingHomework: () -> (vec Homework) query;
    searchHomework: (text) -> (vec Homework) query;
}

Time型

Result型

2023/06/23追記:

5. lib.rsの編集

cargo newコマンドで生成されたlib.rsの中身をクリアして、day2用のプログラムを作成します。

  • addHomework()

  • getHomework()

  • updateHomework()

  • markAsCompleted()

  • deleteHomework()

  • getAllHomework()

  • getPendingHomework()

  • searchHomework()

Rust言語仕様の理解が十分でないため、作成したソースコードは所有権まわりをはじめ最適化されていない可能性がありますのでご注意ください。もしも、おかしな実装等が見つかりましたらが、ご指摘いただけますとさいわいです。

6. Unitテスト

Rustではソース内にUnitテストコードを含めて記述することができます。

TODO: 今回の範囲ではロジックにIC色は無いため、UnitテストはLocal canisterに配備せずそのまま実行する方法としましたが、Canisterに配置したテストの方法は未調査。

$ cargo test

7. Local Canisterの起動

Local Canisterを起動します。

--backgroundオプションでサービス常駐でき、--cleanを付与すると真っ新な状態でLocal canisterを起動できます。

$ dfx start --background --clean

8. Local Canisterへの配備

$ dfx deploy

に相当するcandidを用意します。

Motokoのはint (System time is represent as nanoseconds since 1970-01-01.)のようで、Rust言語ではint128でOKと思われます。

Local caniterに配備してCandid UIで結果を見ると、motokoのはvariant {ok:xxx, err:text}(先頭小文字)となりますが、Rustのはvariant {Ok:xxx, Err:text} (先頭大文字)の違いがあるようです。

そのため、candid定義を Motoko に合わせて、variant { ok:Homework; err: text }とするとRust側でResultを返す際にマッピングエラーとなってしまい、と完全一致とはなりません。

氏より教えていただいた情報より、MotokoのResultに合わせるためにはRust標準のstd::Resultを使用せず、Motokoに合わせてenum型を用意する必要があるようです。

本ドキュメントではstd::Result型を使用する方法説明しますが、MotokoとI/Fを合わせる場合には、氏の内容が参考になります。

と同じように、以下の関数を実装します。

Motoko Bootcamp Day 2
ic-cdk
Cargo.toml
dfx.json
Motoko Bootcamp Day2 📺 Interface
day2.did
Time
Result.Result
Result<T, E>
Motoko Bootcamp Day 2
tokuryoo
tokuryoo
https://github.com/tokuryoo/motokobootcamp-rust-tokuryoo/tree/main/day2/src/day2_backend
Motoko Bootcamp Day 2
lib.rs