Split out from #62, which fixes the symptom client-side. This issue tracks landing the root fix on the network.
The root bug
freenet_git_types::get_state_delta computed:
summary.extension_seqs.get(k).copied().unwrap_or(0) < v.update_seq
unwrap_or(0) conflates "the peer has never seen this key" with "the peer already holds it at seq 0", so any entry written at seq 0 is undeliverable to every peer, permanently. The same shape was present in the refs loop; refs escaped only because the push path happens to always write update_seq >= 1.
Both loops are corrected in source by #62 (None => true, Some(seq) => seq < entry_seq), with unit tests.
Why that fix is not live
get_state_delta is a contract entry point, so it lives in the compiled WASM. crates/freenet-git/contracts/repo-contract.wasm is a checked-in artifact, last built 2026-04-30 (b8edf90), and CI neither rebuilds nor verifies it against the source. So the source and the deployed contract have already diverged, and the corrected get_state_delta reaches nobody until the WASM is rebuilt.
#62 works around this by writing bundle-tip extensions at update_seq = 1, which is deliverable under the deployed rule. That is sufficient for the observed problem and needs no re-key.
What this issue needs
Rebuilding the WASM changes BLAKE3(wasm), and the contract key is BLAKE3(BLAKE3(wasm) || serialize({prefix})) — so every repo re-keys. That is the documented procedure in legacy_contracts.toml:
- Capture the BLAKE3 of the currently-committed
repo-contract.wasm.
- Add a
legacy_contracts.toml entry for it.
- Rebuild, copy the new WASM into
contracts/, ship.
URLs are prefix-based so they do not change; the legacy-fallback path migrates state on first fetch. But it is a network-wide, one-way operation, so it should be a deliberate decision and is best folded into the next planned contract change rather than done for this alone.
Worth fixing at the same time
- CI does not verify the checked-in WASM matches the source. That is what let the divergence go unnoticed. A job that rebuilds the contracts and compares hashes would turn "source says X, network does Y" into a build failure. Note it cannot simply replace the artifact, since that would re-key silently — it should fail and require the deliberate migration step.
- Once the contract is rebuilt, delete the replicated deployed-rule test in
git-remote-freenet (bundle_tip_seq_survives_the_deployed_contracts_delta_rule) and point it at get_state_delta directly. The test says this too.
[AI-assisted - Claude]
Split out from #62, which fixes the symptom client-side. This issue tracks landing the root fix on the network.
The root bug
freenet_git_types::get_state_deltacomputed:unwrap_or(0)conflates "the peer has never seen this key" with "the peer already holds it at seq 0", so any entry written at seq 0 is undeliverable to every peer, permanently. The same shape was present in the refs loop; refs escaped only because the push path happens to always writeupdate_seq >= 1.Both loops are corrected in source by #62 (
None => true,Some(seq) => seq < entry_seq), with unit tests.Why that fix is not live
get_state_deltais a contract entry point, so it lives in the compiled WASM.crates/freenet-git/contracts/repo-contract.wasmis a checked-in artifact, last built 2026-04-30 (b8edf90), and CI neither rebuilds nor verifies it against the source. So the source and the deployed contract have already diverged, and the correctedget_state_deltareaches nobody until the WASM is rebuilt.#62 works around this by writing bundle-tip extensions at
update_seq = 1, which is deliverable under the deployed rule. That is sufficient for the observed problem and needs no re-key.What this issue needs
Rebuilding the WASM changes
BLAKE3(wasm), and the contract key isBLAKE3(BLAKE3(wasm) || serialize({prefix}))— so every repo re-keys. That is the documented procedure inlegacy_contracts.toml:repo-contract.wasm.legacy_contracts.tomlentry for it.contracts/, ship.URLs are prefix-based so they do not change; the legacy-fallback path migrates state on first fetch. But it is a network-wide, one-way operation, so it should be a deliberate decision and is best folded into the next planned contract change rather than done for this alone.
Worth fixing at the same time
git-remote-freenet(bundle_tip_seq_survives_the_deployed_contracts_delta_rule) and point it atget_state_deltadirectly. The test says this too.[AI-assisted - Claude]