bug(native): delayed sync-complete can contaminate a re-added named root's lineage

オープン
#137 コメント 0 件 リアクション 0 件 担当者 0 名 GitHub で見る

メンテナーはふだん 1 日以内に返信

@Seagulls がすでに取り組んでいます。

2026年10月30日 から。

  • #140 @Seagulls による — オープン

評価

難易度
4/5
見積もり時間
3〜5日
初心者へのやさしさ
48/100
issue の種類
バグ
明瞭さ
明確に書かれている
活発さ
活発
技術スタック
go, sqlite

調査の方向性

Start with internal/p2p/routes.go, internal/p2p/syncengine/engine.go, and internal/store/game_roots.go to trace how a named-root report reaches the final SQLite write. Review the linked regression test and reproduction guide, then run the Go race regression suites. Done means stale reports cannot alter a replacement root’s lineage, valid reports still work, and the stated compatibility and build checks pass.

索引モデルが issue の本文から書いたものです。

説明

Summary

A delayed sync-complete event from an authenticated peer can refer to an old mapping of a named root, arrive after that root is removed and re-added under the same name, and populate the replacement mapping's game_root_sync_state with old pulledFiles. Signing/attributing a report to a peer does not prove it refers to the current root incarnation.

Observed defect: persisted stale lineage metadata. This reproduction does not establish a destructive file write or deletion.

Affected source: Liquid-co/OpenSave:dev-public@a0f6032b8ba36da25e3e0e5e90c5ace9ba0c1fc7, with disposable native handler and SQLite fixtures on Linux amd64.

Independent reproduction

Public Go regression · Reproduction guide

git checkout repro/native-root-lineage-import-20261030
go test -count=1 -race -v ./internal/p2p -run '^TestRegressionDelayedReportCannotAttachToReaddedRoot$'
  1. Create a disposable native P2P fixture with an additional mapped config root.
  2. Remove config, then re-add config at a different temporary path. The replacement root's lineage should be empty.
  3. Deliver a sync-complete event attributed to the fixture peer, naming root: config and pulledFiles: ["old-save.bin"] from the old incarnation.
  4. Read game_root_sync_state for the new config.

Stock result: old-save.bin is incorrectly recorded in the new root's lineage. Required result: the report does not mutate the replacement mapping's lineage.

The test uses the native P2P test handler; it is not a test of a complete deployed LAN/relay connection.

Source-level cause

internal/p2p/routes.go accepts a sync-complete event and forwards its root name and file list. internal/p2p/syncengine/engine.go can merge these paths against the current named root based on name alone. internal/store/game_roots.go stores mapping timestamps, but the incoming old event is not bound to the incarnation that produced it.

This is distinct from active-writer-versus-removal: a lock around the removal cannot identify a stale message arriving later.

Bounded suggested fix

Bind a named-root state-bearing report to a receiver-issued mapping generation (for example the receiver's mapped timestamp echoed by the pulling peer) and check that generation in the final authoritative SQLite write. On a missing/old token, do not accept the report as confirmed lineage; fall back to safe fresh manifest reconciliation where appropriate. Preserve current primary-root behaviour and protocol compatibility.

Avoid a global version-vector protocol, new distributed coordinator or general maintenance state.

Acceptance criteria

  • Stock test fails for stale old-save.bin contamination and patched test passes.
  • Old same-name reports cannot affect a replacement root after remove/re-add, including rapid re-add and remap.
  • Valid new-root reports are recorded; LAN/relay callbacks and deletion lineage still behave correctly.
  • Older peers lacking a generation token fail safely or reconcile with documented compatibility limits.
  • Go/race regression suites and supported builds pass.

Evidence limit: No claim of user-save loss or that a full two-daemon delayed delivery has been executed by this public test.


Independent public reproducer and original report: https://github.com/Seagulls/OpenSave/issues/14.

主要言語
Go
スター
225
フォーク
9
平均マージ
1日 22時間
マージ済み PR(30日)
75

環境構築

  • Dockerfile または Docker Compose ファイルあり
  • プルリクエストのテンプレートなし
  • コントリビューションガイドなし

はじめの一歩

  1. issue を最後まで読み、次にプロジェクトのコントリビューションガイドを読みます。
  2. 着手することを issue にコメントします — 二人が同じ作業をするのを防げます。
  3. リポジトリをフォークし、ブランチを切って変更します。
  4. issue 番号を参照したプルリクエストを送ります。

Liquid-co/OpenSave のほかの issue

Liquid-co/OpenSave の issue をすべて見る

似ている issue

Go の issue をもっと見る

新しい issue をメールで受け取る

初心者向けの GitHub issue を短くまとめたダイジェスト。