📘 Academy原文準拠 | Phase 3 · Unit 1 · Lesson 1.2 Compact Language Fundamentals 内容に忠実な日本語版です。原文(英語)・動画は公式 Academy(外部リンク・別タブで開きます)、文法の正本はCompact リファレンス(外部リンク・別タブで開きます)を。
JavaScript / TypeScript など C 系の言語を書いたことがあれば、Compact は一見なじみがあります(セミコロン、波かっこ、if 文…)。でも Compact は汎用言語ではありません。Midnight 上で動くゼロ知識回路を定義するという、ただ1つの目的のために作られています。
その制約が言語のすべてを形づくります。TypeScript で当たり前のものが無かったり、逆に disclose のような一見へんなものが「プライバシーの核心」だったりします。
動画で学ぶ(公式)
Compact プログラムの骨格
どの Compact も同じ基本構造です。次のレッスンでデプロイする hello-world 契約を見てみましょう。
これで完全な・デプロイ可能な契約です。実質6行。順に分解します。
pragma(バージョン宣言)
どのバージョンの Compact 向けかをコンパイラに伝えます。省略可ですが必ず書くべき。Compact は進化中で、マイナー更新に破壊的変更が入ることがあるためです。
- 範囲指定OK:
>= 0.20 && <= 0.22。>= 0.20単独なら「0.20 以上」。 - パッチ番号(0.20.0 など)は書かない。マイナー番号まで。
import(標準ライブラリ)
Counter / Map / Set などの型や、persistentHash などの組み込み回路が使えるようになります。
※ disclose は言語そのものの一部で、import 不要・常に使えます。
ledger 宣言(公開状態)
ここが Solidity 等と大きく違うところ。契約の本体(contract body)が無く、ledger 宣言はトップレベルに書きます。
- 各
ledger宣言は、Midnight の公開台帳に永続保存されるデータ。 exportを付けると、DApp のフロント(TS SDK)から読めるようになる。付けないと、チェーン上には在るが外から読めない。sealedを付けると、constructor で一度だけ設定でき、その後は変更不可。
データ型
ZK 回路で効率よく証明できることを軸に設計された、絞り込まれた型システムです。普通の意味での文字列・配列・オブジェクトはありません。
プリミティブ型

コレクション型

Counter… 特別。直接代入せず、.increment(n)/.decrement(n)/.read()で操作。並行トランザクションを正しく扱うため。Map/Set… 期待どおり。しかも.lookup()/.member()/.isEmpty()/.size()などの問い合わせは回路内でも動く。
カスタム型(enum / struct)
circuit(オンチェーンの関数)
circuit は、ZK回路にコンパイルされる関数です。誰かが呼ぶと、prover が「計算は正しく行われた」という ZK 証明を作り、ネットワークがそれを検証します。
- 戻り型
[](空タプル)=値を返さない。Compact にVoidは無く、[]が Void の代わり(古い例でVoidを見たら[]に読み替え)。 - 値も返せます:
- 修飾子:
disclose キーワード(最重要)
Compact は「プライバシーがデフォルト」という厳格なルールを持ちます。
- 回路パラメータや witness から来た値は、コンパイラが秘密とみなす。
- その値を公開台帳に書くなら、
disclose()で囲んで「これは意図的に公開してよい」と明示する必要があります。
囲まないと、コンパイラが “implicit disclosure” エラーで止めます(うっかり漏洩の防止)。
さらに、witness 由来の値で分岐するときも disclose が要ります。
ルールは単純:秘密の値が「公開のなにか(台帳書き込み/公開状態に影響する分岐)」に影響するなら、disclose が必要。
型キャスト
Compact はキャストに厳格です。許されたキャストだけが可能で、static / conversion / 実行時チェックに分類されます。 Field ↔ Bytes<n>、Uint<0..m> ↔ Uint<0..n> などはキャスト表で定義された範囲でのみ可能。表に無いキャストは不可(→ 公式 lang-ref の cast 表(外部リンク・別タブで開きます))。
constructor(初期化)
省略可。デプロイ時に一度だけ実行され、初期値(特に sealed フィールド)を設定します。
デプロイ後は二度と呼べず、sealed は変更不可。
assert(条件チェック)
失敗すると回路全体が失敗し、取引は拒否されます。エラーメッセージは開発者向けで、オンチェーンには現れません。
組み込み関数の注意

標準ライブラリは persistentHash などを提供します。ただし:
⚠️
public_key()は組み込み関数ではありません(そう見える例があるが誤り)。公開鍵の導出はpersistentHashパターンで行います。
pad(32, "myapp:pk:") のようなラベル(ドメイン分離)を混ぜるのがポイントです(用途ごとにハッシュを分ける)。
開発者として押さえる点
- 骨格:pragma → import → ledger(トップレベル)→ circuit。契約本体ブロックは無い
- 公開は
ledger、秘密は witness、境目にdisclose。witness 由来の分岐にもdiscloseが要る(ここが落とし穴) []は Void の代わり。pure circuitは状態に触れないユーティリティ- 型は ZK 前提(
Field/Uint<N>/Bytes<n>/Opaque<...>)。Counterは.increment/.read、Map/Setの問い合わせは回路内でも動く - キャストは表にあるものだけ。
public_key()は組み込みでない=persistentHashパターンで作る
やさしい版・公式へ
- やさしい版:Compactってなに? / Compactの書きかた(文法ツアー)
- 公式:Compact リファレンス(外部リンク・別タブで開きます) / Academy Phase 3 / Unit 1 / 1.2(外部リンク・別タブで開きます)
つぎに読むページ
➡️ 原文準拠コースの入口へ戻る。このコースについて(次のレッスンは順次追加します)