2つめは Bulletin Board(けいじ板)。 メッセージを貼って、あとで自分だけが取り下げられる――しかもだれが貼ったかはチェーン上に出さない。Midnight らしさが出てきます。
何を作るの?
- 1枚の board にメッセージを貼る(post)
- 貼った本人だけが取り下げる(takeDown)
- でも「本人」を公開のIDで持たない(名前は出さない)
何を学べるの?
- 状態を
enum(空き/使用中)で表す - コミットメント(秘密のカギから作るハッシュ)で「本人」を表す
witnessで秘密のカギを渡し、discloseで公開してよい値だけ出す- TypeScript で API クラスを作り、画面とつなぐ
たとえ話:合言葉で取り下げる
掲示板に紙を貼るとき、名前を書くかわりに「自分だけ作れる合言葉のハンコ」を押すとします。 取り下げたい人は、同じハンコをもう一度作って「ほら、同じでしょ」と示す。 名前は分からないのに、本人だけが取り下げられる。これがコミットメントの考えかたです。
契約の中身(本物・短い)
bboard.compact(一部)
ポイント:
ownerには公開鍵そのものではなく、秘密カギから作ったハッシュ(ハンコ)を入れる。だから名前は分からない。takeDownで「もう一度同じハンコを作って一致するか」をassertで確認 → 本人だけ通る。- 秘密カギ由来の値を公開する所には、必ず
disclose。
プロジェクトの形
TS 側のしくみ(雰囲気)
API クラスが、契約の呼び出しをやさしいメソッドにまとめます。
さらに、公開状態(indexer)+手元の秘密を合わせて「自分が owner かどうか」を計算し、画面に出します(RxJS で常に最新に)。
3つの部屋:Contract・API・CLI(Academy Unit 3〜4)
公式の Bulletin Board チュートリアルは、3つの部屋(パッケージ)に分かれています。Academy の Unit 3〜4 はこの3つを順に作ります。
① Contract(契約)
このページの「契約の中身」がこれ。compact compile で TS API・ZK鍵・回路が生成されます。
② API Layer(つなぎの層)
契約をそのまま使うと大変なので、BBoardAPI クラスで包みます。
deploy()/join():新しく置く/既にあるものに参加するpost()/takeDown():貼る/取り下げるstate$:公開状態+手元の秘密を合わせた「いまの状態」を流し続ける(owner 判定もここ)
→ 画面や CLI は、この API クラスだけ見ればよくなります(関心の分離)。
③ CLI と デプロイ
- CLI は
BBoardAPIを呼ぶだけのうすいアプリ(メニューで post / takeDown)。 - 動かすには providers(indexer / proof server / wallet …)をそろえます(→ DApp の組み立てかた)。
④ Preprod へデプロイ(Academy Unit 4.1)
- まずローカルの undeployed(自分だけのネット)で試す。
- うまくいったら Preprod(公開テストネット)へ。tNIGHT を faucet でもらい、tDUST を生成して手数料にします(→ 開発環境)。
- 設定で「つなぎ先(indexer / node / proof server / network id)」を Preprod に切りかえます。
卒業制作として、この板を自分で拡張してみましょう → Capstone:けいじ板を拡張する
進む前に理解しておくこと
- Counter を一周していること
- 必要なことだけ見せる(コミットメントの考えかた)
- Compact の書きかた(
witnessとdisclose)
開発者として理解すべきこと
- 公開IDを持たずに本人確認する=コミットメント(ハッシュ)と ZK の典型パターン
assertで「本人だけ」を強制し、discloseで漏洩をコントロールする- 契約の上に API レイヤーを作ると、画面側がぐっと書きやすくなる
公式Docsではどこ?
- Bulletin board: smart contract(外部リンク・別タブで開きます)
- Bulletin board: API / CLI 実装(外部リンク・別タブで開きます)
- ソース:example-bboard(外部リンク・別タブで開きます)
今日のまとめ
- けいじ板=「名前を出さずに、本人だけ取り下げ」
- カギは コミットメント(秘密カギ→ハッシュ) と
assertとdisclose - 契約の上に API クラスを作って画面とつなぐ
今はここだけでOK
「owner に入れるのは名前じゃなくて、本人だけ作れるハンコ(ハッシュ)」——これが分かれば大きな前進です。
✍️ 白紙練習
答えを見る前に、いったん自分の頭と手から出してみよう。手で書くと「わかったつもり」がはがれます。
bboard.compact の ledger 宣言3つ(state / message / owner)を、型もコメントもそのまま書いてみよう。
post circuit を再現してみよう。assert・disclose・状態の更新まで含めて。
「名前を出さずに、本人だけが取り下げできる」しくみを、コミットメントという言葉を使って自分のことばで説明してみよう。
owner には公開鍵そのものではなく、秘密カギから作ったハッシュ(ハンコ=コミットメント)を入れる。だから誰が貼ったかは分からない。取り下げ(takeDown)のときに、もう一度同じ秘密カギからハンコを作り、owner と一致するかを assert で確認する。一致するのは本人だけなので、名前を出さなくても本人だけが取り下げられる。
ledger owner には何を入れる?公開鍵そのもの?
公開鍵そのものではなく、秘密カギから作ったハッシュ(ハンコ=コミットメント)を入れる。だから名前(公開ID)は分からない。
takeDown が「本人だけ通る」のはなぜ?
もう一度同じ秘密カギからハンコ(publicKey)を作り、owner と一致するかを assert で確認するから。一致するハンコを作れるのは本人だけなので、本人だけが通る。
秘密カギ由来の値を公開状態に入れるとき、必ず付けるものは?
disclose。秘密カギ由来の値を公開する所には必ず disclose を付けて、漏洩をコントロールする。
state は何で表す?その2つの値は?
enum の State で表す。値は VACANT(空き)と OCCUPIED(使用中)の2つ。
BBoardAPI クラスは何のためにある?
契約をそのまま使うと大変なので、契約の呼び出しをやさしいメソッド(deploy / join / post / takeDown など)に包むため。画面や CLI はこの API クラスだけ見ればよくなる(関心の分離)。
📘 もっと正確に(原文準拠コース)
Academy 原文に忠実な詳しい版はこちら:
つぎに読むページ
➡️ 相手にぜったい見せない状態を扱う。Battleship チュートリアル