midnight-compact
Midnightのコンパクトスマートコントラクトを作成、テスト、デプロイできます。プライバシー保護型のコントラクト、ZK回路、シールドトークン、またはMidnight上のオンチェーンコード全般を記述する際に使用します。Midnight、Compact、スマートコントラクト、ゼロ知識証明、ZK、シールド、回路、ウィットネス、台帳、プルーフサーバー、DUST、NIGHT、disclose、Zswapといったキーワードをトリガーとして動作します。Compact言語の構文、プライバシーモデル、回路パターン、テスト、セキュリティベストプラクティス、SDKインテグレーション、ウォレット連携に対応しています。
description の原文を見る
Write, test, and deploy Compact smart contracts for Midnight. Use when writing privacy-preserving contracts, ZK circuits, shielded tokens, or any on-chain Midnight code. Triggers on: Midnight, Compact, smart contract, zero-knowledge, ZK, shielded, circuit, witness, ledger, proof server, DUST, NIGHT, disclose, Zswap. Covers Compact language syntax, privacy model, circuit patterns, testing, security best practices, SDK integration, and wallet connectivity.
SKILL.md 本文
Midnight Compact スマートコントラクト開発
あなたはMidnightスマートコントラクト開発の専門家です。CompactはTypeScriptに似たドメイン固有言語で、ゼロ知識回路にコンパイルされ、Midnightブロックチェーンでプライバシーを保護する計算を実現します。
コア原則
- デフォルトでプライベート — すべての計算は、
disclose()で明示的に開示しない限りプライベートです。 - デュアルステートモデル — コントラクトは公開レジャー状態(オンチェーン)とプライベート状態(オフチェーン、ユーザー単位)を持ちます。
- 関数ではなく回路 — エクスポートされた
circuit宣言はZKプルーフにコンパイルされます。functionキーワードは存在しません。 - ウィットネスはプライベートデータをブリッジ — Compactの
witness宣言はTypeScriptで実装され、オフチェーンのプライベート入力を提供します。 - 正確性は強制される — すべての回路計算はZKプルーフで検証されます。ウィットネスコードのみが未検証で実行されます。
- すべてテストする — Compactシミュレータを使用してから、スタンドアロンネットワーク、その後テストネットで行います。
判断木
スマートコントラクトの作成を依頼されたとき:
- コントラクトを指定する — コード作成前に以下を定義します:
- どの状態が公開対プライベート?
- どの操作(回路)を公開しますか?
- どの不変条件が成立する必要がありますか? (例:「総供給量は保存される」「所有者のみが引き出せる」)
- 信頼境界は何ですか? (ウィットネスは何について嘘をつく可能性がありますか?)
- 失敗モードは何ですか?
- プライバシー要件を特定 — 何がシールドされる必要があり、何が公開ですか?
- レジャー状態を設計 — 公開は
export ledger、コントラクトプライベートは通常のledger - ウィットネスを設計 — ユーザーがオフチェーンで提供するプライベートデータは?
- 回路を記述 — エクスポートされたもの(外部呼び出し用)とプレーン(内部用)
disclose()呼び出しを追加 — ウィットネス派生値をレジャーに書き込むか、条件分岐で使用する場合は必須- TypeScriptウィットネスを記述 —
[newPrivateState, returnValue]を返すウィットネス本体を実装 - テストを記述 — プログレッシブなアプローチ:
- ユニットテスト(ウィットネスを独立してテスト、正しい型、不変状態、エッジケース)
- シミュレータテスト(すべての回路、ハッピーパス+エラー条件)
- 不変テスト(
fast-checkで保存法、状態マシン妥当性) - プライバシーリークテスト(秘密が公開状態に現れないこと確認)
- 敵対的テスト(リプレイ攻撃、権限昇格、悪意あるウィットネス)
- プライバシーリークを確認 — security.mdのセキュリティパターンを確認
- 回路の複雑性を確認 — k値が許容範囲内(k <= 14は高速、k >= 17は最適化必要)
- コンパイルとデプロイ —
compact compile、プルーフサーバーでテスト、メインネット前にpreprodにデプロイ
コントラクトの監査またはレビューを依頼されたとき:
- auditing.mdの監査方法論に従う
- フェーズ1: レジャー状態、回路、ウィットネス、信頼境界をマップ
- フェーズ2: プライバシーリークスキャン — すべての
disclose()呼び出し、ウィットネス相互作用、間接的リークを確認 - フェーズ3: 回路複雑性分析 — k値、レジャー操作コストを確認
- フェーズ4: SDK統合レビュー — バージョン整合、プロバイダ設定
- フェーズ5: テストカバレッジ評価
- 発見事項をレポート — 重大度、プライバシー影響、修正方法を含める
Compact言語 — 必須構文
プラグマ(すべてのファイルの最上部に必須)
pragma language_version >= 0.20;
インポート
import CompactStandardLibrary; // 常に必須
import "./path/to/Module" prefix Module_; // OZ合成パターン
レジャー宣言
重要: 個別ステートメントを使用します。ブロック構文ledger { }は廃止予定で、パース エラーが発生します。
export ledger counter: Counter; // 公開、誰でも読める
export ledger owner: Bytes<32>; // 公開
export sealed ledger name: Opaque<"string">; // コンストラクタで一度設定、不変
ledger privateData: Field; // エクスポートなし = コントラクトプライベート
型
プリミティブ:
| 型 | 説明 |
|---|---|
Field | 有限体要素(ZK回路の基本数値型) |
Boolean | true/false |
Bytes<N> | 固定サイズバイト配列(N=32が一般的) |
Uint<N> | 符号なし整数(N = 8, 16, 32, 64, 128)。注: Uint<256>は非サポート |
Uint<MIN..MAX> | 境界付き符号なし整数 |
Opaque<"string"> | TypeScriptからブリッジされた外部型 |
コレクション:
| 型 | 説明 |
|---|---|
Counter | インクリメント/デクリメント可能なカウンタ(レジャーバック) |
Map<K, V> | キー値マッピング(レジャーバック、コストがかかる) |
Set<T> | 一意値コレクション(レジャーバック、コストがかかる) |
Vector<N, T> | 固定サイズ配列(回路フレンドリー) |
Maybe<T> | オプション値 — some<T>(val) / none<T>() |
Either<L, R> | ユニオン型 — left<L, R>(val) / right<L, R>(val) |
Midnight固有:
| 型 | 説明 |
|---|---|
ZswapCoinPublicKey | コイン操作用ウォレット公開鍵 |
ContractAddress | オンチェーンコントラクトアドレス |
CoinInfo | シールドトークン用コイン記述子 |
カスタム型:
export enum GameState { waiting, playing, finished }
export struct PlayerConfig { name: Opaque<"string">, score: Uint<32> }
注: 列挙値はドット記法を使用: GameState.waiting、NOT GameState::waiting。
回路
// エクスポート回路 — TypeScriptから呼び出し可、ZKプルーフ生成
export circuit increment(): [] {
counter.increment(1);
}
// パラメータと戻り値を持つ回路
export circuit getBalance(addr: Bytes<32>): Uint<64> {
return balances.lookup(addr);
}
// 内部回路 — エクスポートなし、他の回路からのみ呼び出し可
circuit validateOwner(caller: Bytes<32>): Boolean {
return caller == owner;
}
// 純粋回路 — 状態アクセスなし、副作用なし
export pure circuit hash(data: Bytes<32>): Bytes<32> {
return persistentHash<Vector<1, Bytes<32>>>([data]);
}
重要: 戻り値型は[](空タプル)です。void回路にはVoidではありません。functionキーワードは存在しません — ステートレス計算にはpure circuitを使用します。
ウィットネス
Compactで宣言(本体なし)、TypeScriptで実装:
// Compact — 宣言のみ、セミコロンで終了
witness localSecretKey(): Bytes<32>;
witness getAmount(max: Uint<64>): Uint<64>;
// TypeScript — [newPrivateState, returnValue]を返す実装
export const witnesses = {
localSecretKey: ({ privateState }: WitnessContext<Ledger, PrivateState>):
[PrivateState, Uint8Array] => [privateState, privateState.secretKey],
getAmount: ({ privateState }: WitnessContext<Ledger, PrivateState>, max: bigint):
[PrivateState, bigint] => [privateState, privateState.amount],
};
開示 — コアプライバシープリミティブ
// ウィットネス派生値をレジャーに書き込むか条件で使用する場合は必須
owner = disclose(publicKey(localSecretKey()));
// プライベート値のアサーション
assert(disclose(caller == storedOwner), "Not authorized");
// プライベート値に基づく分岐
if (disclose(guess == secret)) { /* ... */ }
重要: Compact 0.16以降、disclose()はすべてのウィットネス派生値をレジャー状態に書き込むか制御フロー影響のブール式で使用する場合に必須です。省略するとコンパイルエラーが発生します。
コンストラクタ
constructor() {
counter.increment(1);
owner = disclose(publicKey(localSecretKey()));
}
一般的な操作
// カウンタ
counter.increment(1); counter.decrement(1);
counter.read(); counter.lessThan(100);
// マップ
balances.insert(key, value); balances.remove(key);
balances.lookup(key); balances.member(key);
// Maybe
const opt = some<Field>(42); const empty = none<Field>();
if (opt.is_some) { const val = opt.value; }
// Either(ウォレットまたはコントラクトアドレスに使用)
const wallet = left<ZswapCoinPublicKey, ContractAddress>(ownPublicKey());
const contract = right<ZswapCoinPublicKey, ContractAddress>(kernel.self());
// ハッシング
persistentHash<Vector<2, Bytes<32>>>([data1, data2]); // SHA-256
transientHash<Vector<2, Bytes<32>>>([data1, data2]); // Poseidon(回路内で10倍安価)
// 型キャスト
const bytes: Bytes<32> = myField as Bytes<32>;
const num: Uint<64> = myField as Uint<64>;
// アサーション
assert(condition, "Error message");
コイン操作(シールドトークン)
receive(coin); // 入ってくるコインを受け入れ
sendImmediate(coin, recipient, amount); // コインを送出
mintShieldedToken(domainSeparator, amount, nonce, recipient); // 新トークンを作成
tokenType(pad(32, "myToken"), kernel.self()); // トークン型IDを取得
CLIワークフロー
# Compactツールチェーンのインストール/更新
curl --proto '=https' --tlsv1.2 -LsSf \
https://github.com/midnightntwrk/compact/releases/latest/download/compact-installer.sh | sh
compact self update # 開発ツールを最初に更新
compact update 0.29.0 # その後ツールチェーンを更新
# スキャフォルド、コンパイル、テスト
npx create-mn-app my-project # 新規プロジェクトをスキャフォルド
compact compile src/contract.compact src/managed/contract # コンパイル
compact fmt src/contract.compact # フォーマット(コンパイラ0.25.0以上)
npm test # テスト実行(Vitest/Jest)
テスト
デプロイ前に必ずシミュレータでテストします。不変性テスト、ウィットネス検証、敵対的テスト、パフォーマンス基準、CI/CD統合の詳細はtesting.mdを参照してください。
import { Contract } from "../managed/counter/contract/index.js";
import { createConstructorContext, createCircuitContext, sampleContractAddress } from "@midnight-ntwrk/compact-runtime";
import { setNetworkId } from "@midnight-ntwrk/midnight-js-network-id";
setNetworkId("undeployed");
// ウィットネスでコントラクトインスタンスを作成
const contract = new Contract<PrivateState>(witnesses);
// 初期化 — sampleContractAddress()は関数、呼び出します
const addr = sampleContractAddress();
const initial = contract.initialState(createConstructorContext(initialPrivateState, addr));
// 最初の回路コンテキストを作成 — 4つのパラメータが必須: (address, zswapState, contractState, privateState)
const ctx = createCircuitContext(addr, initial.currentZswapLocalState, initial.currentContractState, initial.currentPrivateState);
// 回路を実行
const result = contract.impureCircuits.increment(ctx);
// 呼び出しをチェーン: result.contextを直接渡します — これが継続です
const readResult = contract.impureCircuits.read(result.context);
console.log(readResult.result); // 1n
DUSTフィー経済学
DUSTはMidnightのフィートークンです — tNight保有から継続的に生成される高精度マイクロトークンです。すべてのトランザクションフィーはDUSTで支払われます。
生成モデル
| パラメータ | 値 | 意味 |
|---|---|---|
nightDustRatio | 5,000,000,000 | tNight1個あたり1秒当たりのピークDUST生成量 |
timeToCapSeconds | 604,815 | 生成上限に達するまでの時間(約7日) |
generationDecayRate | 8,267 | 生成曲線の減衰係数 |
dustGracePeriodSeconds | 10,800 | 生成が減衰し始める前の3時間のグレース期間 |
DUSTに小数点はありません — 値は最小の不可分単位です。数値は意図的に大きく、フィー計算の高精度を提供します。
デプロイコスト(preprod、プロトコルv21000)
2026年3月のpreprodでの13のコントラクトデプロイメントから測定:
| 複雑性 | フィー範囲 | 例 |
|---|---|---|
| シンプル(3回路) | 331B–367B DUST | Counter、RPS、Upgrade-V1、Token Minting |
| 中程度(5回路) | 479B–564B DUST | Credential、DID、Prescription、Market、Staking、Crowdfunding |
| 複雑(6-7回路) | 629B–721B DUST | NFT、DAO、Lending、Upgrade-V2 |
- フィーは決定的 —
paidFeesはestimatedFeesと完全に一致 - デプロイ時間: 16–22秒(ZKプルーフ生成+オンチェーン確認を含む)
- 2,000 tNightを保有すれば、DUST生成がデプロイフィーを上回ります — 13のコントラクトすべてがDUSTに余裕を持ってデプロイされました
実用的なガイダンス
- DUSTはtNightから受動的に蓄積 — 明示的な変換不要
DustWalletSDKがフィー計算と支払いを自動的に処理DustWallet設定でadditionalFeeOverheadを設定してフィーバッファを確保(デフォルト例は300T DUST)- preprodではMidnightフォーセットからtNightをリクエスト — 1リクエスト1,000 tNightで数十のデプロイに十分
リファレンス資料
詳細情報については以下を参照してください:
- 言語リファレンス — 型、構文、モジュール、キャスト、演算子
- プライバシーモデル — シールド対非シールド、disclose()、ウィットネスパターン、ZK基礎
- セキュリティパターン — ZK固有攻撃ベクトル、プライバシーリーク、一般的エラー
- テストガイド — シミュレータ、不変性テスト、ウィットネス検証、敵対的テスト、CI/CD、パフォーマンス基準
- 設計パターン — 回路最適化、オフチェーン計算、モジュール合成
- 標準ライブラリ — CompactStandardLibrary組み込み関数と型
- 落とし穴 — 52のコンパイラバグ、SDKピットフォール、設計トラップ(Discord +実際のコンパイル)
- オフチェーン統合 — TypeScript SDK、ウォレット、デプロイ、コントラクト監視、エラーハンドリング
- 監査方法論 — ZKコントラクト監査プロセス、プライバシーリーク検出
例
29の例(検証済み27個+ネットワーク専用2個)。151の回路がコンパイルされ、182/182テストに合格、30のコントラクトがpreprodにデプロイされています:
コアパターン:
- Counter — 3回路、5/5テスト。最もシンプルなコントラクト、インクリメント/デクリメント。
- Bulletin Board — 3回路、8/8テスト。ウィットネス認証、所有権、CRUD。
- Fungible Token — 7回路、6/6テスト。ERC20相当、OZモジュール合成。
- NFT — 7回路、6/6テスト。コミットメントベース所有権、ミント/バーン/転送/承認。
- Rock-Paper-Scissors — 3回路、6/6テスト。最小のコミット-リビール2プレイヤーゲーム。
プライバシーパターン:
- Shielded Voting — 6回路、9/9テスト。コミット-リビール秘密投票。
- Sealed-Bid Auction — 6回路、8/8テスト。コミット-リビールとZK検証付き。
- Identity Proof — 4回路、6/6テスト。選択的開示、パラメータ化ウィットネス。
- Credential Registry — 5回路、6/6テスト。ヌリファイアベースの二重使用防止。
- Prescription — 5回路、6/6テスト。Vectorを使った一括登録、二重充填防止用ヌリファイア。
- Privacy Mixer — 3回路、7/7テスト。コミットメントデポジット、ヌリファイア出金。
DeFi &エスクロー:
- Escrow — 5回路、8/8テスト。2者間条件付き交換、期限付き。
- Time Lock — 3回路、7/7テスト。LOK/RELEASEパターン(時間制限付き資産リリース)。
- Multi-Sig — 6回路、6/6テスト。M-of-N認可、複合鍵。
- Staking — 5回路、6/6テスト。ロック期間、ZKフレンドリー報酬計算。
- Crowdfunding — 5回路、6/6テスト。匿名バック、ZK払い戻しプルーフ。
- Lending — 6回路、6/6テスト。担保、健全性係数、清算。
- Prediction Market — 5回路、7/7テスト。コミットメントベット、ZK支払い。
- Vesting — 4回路、8/8テスト。時間ベーストランシェリリーススケジュール。
- Revenue Sharing — 3回路、7/7テスト。プライベート配分、ZK出金。
- Lottery — 4回路、8/8テスト。コミット-リビール多者ランダム性。
高度な:
- Oracle Feed — 5回路、6/6テスト。外部データ、鮮度チェック。
- Token Swap — 6回路。
receiveShielded/sendImmediateShieldedを使った原子交換、preprodデプロイ。 - Access Control — 8回路、6/6テスト。ロール階層、内部ガード。
- DID Registry — 5回路、6/6テスト。ドキュメントライフサイクル(作成/更新/非アクティブ化)。
- Micro-DAO — 7回路、7/7テスト。トークンゲート投票、財務、ガバナンス。
- Contract Upgradability — V1: 3 + V2: 7回路、8/8テスト。マイグレーションパターン。
- Token Minting — 3回路。Zswapコイン作成(
mintShieldedToken)、preprodデプロイ。 - Supply Chain — 4回路、7/7テスト。選択的開示サプライチェーン追跡。
本番参考資料
実装を研究するためのオープンソースMidnightコントラクトとツール:
OpenZeppelin Compact Contracts(正規リファレンス):
- OpenZeppelin/compact-contracts — Ownable、Pausable、AccessControl、FungibleToken、Capped、Nonces。モジュール合成パターン。本番グレード。
Brick Towers(最も活発なコミュニティビルダー):
- midnight-seabattle — フルスタックdApp(ゲーム)。マルチユーザー、シールド状態、E2Eテスト。実dAppアーキテクチャの最良リファレンス。
- midnight-local-network — ローカル開発用Docker Compose(ノード+インデクサー+プルーフサーバー)。コミュニティ標準。
- midnight-proof-server — 事前設定済みプルーフサーバー(回路パラメータ付き)。ダウンロードタイムアウト排除。
- midnight-rwa — 現実資産トークン化。
公式Midnightの例:
- example-counter — 公式counter(最もシンプル)。
create-mn-appのテンプレート。 - example-bboard — 公式掲示板。ウィットネス+認証パターンの正規実装。
- midnight-awesome-dapps — キュレートされたコミュニティdAppsリスト。
コミュニティプロジェクト:
- midnight-kitties — CryptoKitties風NFT dApp。
- compact-by-example — 実践例でCompactを学ぶ。
- pulse-finance/midnight-dex-contract — CompactでのAMM DEX。
開発者ツール:
- midnight-mcp — Midnight用MCPサーバー(Idris、Midnightチーム)。
- compact-vscode — VSCode構文ハイライ
ライセンス: MIT(寛容ライセンスのため全文を引用しています) · 原本リポジトリ
詳細情報
- 作者
- ADAvault
- ライセンス
- MIT
- 最終更新
- 2026/3/29
Source: https://github.com/ADAvault/midnight-skill / ライセンス: MIT