Skip to content

fix(state-node): bootstrap content network on first push to eliminate create race#41

Open
somasekimoto wants to merge 4 commits intomainfrom
fix/create-content-push-race
Open

fix(state-node): bootstrap content network on first push to eliminate create race#41
somasekimoto wants to merge 4 commits intomainfrom
fix/create-content-push-race

Conversation

@somasekimoto
Copy link
Copy Markdown
Contributor

@somasekimoto somasekimoto commented Apr 11, 2026

Summary

  • create_contentPushOperations を member ノードに送る際、受信側がまだ ContentNetwork を知らないため push が拒否され、member にデータが届かない問題を修正
  • creator ノードが selected から自身を除外しているのに、ローカル CRDT と AccessPolicy を保存していた問題を修正

修正方針

  • ContentRequest::PushOperations に optional な PushBootstrap { creator_node_id, member_nodes, created_at } を追加
  • 受信側は「既存ネットワークあり → 厳格なメンバー検証 / 既存なし + bootstrap → creator 検証 + self-in-members 検証 + ContentNetwork 即時保存 / それ以外 → 拒否」の順で判定
  • crdt_repoprepare_create_operations を追加し、ephemeral な CrslCrdtRepository 上で create を走らせて SerializedOperation を抽出 → creator は CRDT を永続化しない
  • creator は ContentNetwork メタデータだけ は保存する (relay 経路が member 一覧を必要とするため)
  • push 全失敗時は保存した ContentNetwork を rollback

セキュリティ

peer_id == bs.creator_node_idlocal_peer_id in bs.member_nodes を要求するので、creator なりすまし・victim へのネットワーク押し付けは防げる。残余リスク (任意 peer が自称 creator として push) は既存 Gossipsub ContentCreated の信頼モデルと同等。該当箇所に SECURITY: コメント記載。

互換性

Wire 形式変更あり。旧ノードとは通信不可になる。

Test plan

  • cargo test -p monas-state-node 329 passed (286 unit + 5 e2e + 32 integration + 4 pk exchange + 2 new)
    • 新規 tests/create_content_push_race_test.rs:
      • create_content_delivers_crdt_ops_to_members_without_gossipsub_sync — 3 ノード実 libp2p mesh で create_content、gossipsub settle を挟まずに member がデータを持つこと + creator は持たないことを検証
      • push_operations_rejects_unknown_network_without_bootstrap — 拒否パスの回帰防止
    • 新規 unit test_prepare_create_operations_is_deterministic_across_repos — creator が持たない / 受信側が同じ CID で復元できること
  • cargo test --workspace --profile test 603 passed
  • cargo fmt --check
  • cargo clippy --workspace --all-targets --profile test --no-deps -- --deny warnings 警告 0
  • 3 ノードローカル e2e (scripts/start-local-nodes.sh --cleanscripts/e2e-test.sh) 7/7 passed
    • scripts/e2e-test.sh に Step 2.5「作成直後の即時同期検証」を追加 (race の回帰防止アサーション)

🤖 Generated with Claude Code

somasekimoto and others added 4 commits April 15, 2026 20:18
… create race

create_content pushed CRDT operations to selected members before the
Gossipsub ContentCreated event arrived, so the PushOperations handler
rejected the push for an unknown network. Members ended up with
metadata but no data. The creator also retained a local CRDT copy
despite being excluded from the member set.

Carry a PushBootstrap payload on the first push so the receiver can
persist the ContentNetwork record inline, and build the ops in an
ephemeral CRDT repo so the creator no longer stores content it doesn't
own. The creator still keeps the network metadata for relay purposes.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…otstrap

Keep the common update/delete/sync path free of the bootstrap parameter.
Only create_content uses the _with_bootstrap variant.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace the ephemeral LevelDB approach with direct Node construction
and content_id() calls from crsl-lib. No I/O or temp files needed —
genesis CID and update CID are computed via CBOR serialization + SHA-256
in memory. tempfile moves back to dev-dependencies.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@somasekimoto somasekimoto force-pushed the fix/create-content-push-race branch from c539438 to ed876bb Compare April 15, 2026 11:22
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant