Skip to content

Contract WASM versioning: prevent key mismatch between components #54

@sanity

Description

@sanity

Problem

Contract keys in Freenet are derived from hash(parameters + contract_code). When different components use different versions of the same contract WASM, they compute different contract keys, causing operations to fail with "contract not found" errors.

Recent Incident

The multi-peer test in cli/tests/message_flow.rs was failing because:

  1. The test used include_bytes!("../contracts/room_contract.wasm") (stale copy)
  2. The riverctl binary used include_bytes!(concat!(env!("OUT_DIR"), "/room_contract.wasm")) from build.rs
  3. build.rs prioritizes ui/public/contracts/room_contract.wasm

When these files drifted out of sync, the test would:

  • Create a room (PUT with contract key A)
  • Reconstruct the contract key using stale WASM (contract key B)
  • Try to GET/Subscribe to key B → NotFound

Fixed in c28ffef by pointing the test to the canonical source.

Broader Concern

This pattern could cause issues in production:

  • Different River builds (UI vs CLI) deployed with different contract WASM versions
  • Users trying to join rooms created with a different version
  • Any component that reconstructs contract keys must use identical WASM

Current Mitigations

  1. cli/build.rs has verify_matches_built_artifact() that checks against release WASM
  2. .github/workflows/check-cli-wasm.yml checks for drift in CI
  3. cargo make sync-cli-wasm task to manually sync

Potential Solutions

  1. Single source of truth: Remove all copies, always build and reference from one location

  2. Hash-based verification: At runtime, verify the WASM hash matches expected value before using it for key derivation

  3. Contract registry: Store contract code hashes in a manifest that all components reference

  4. Compile-time check: Macro that verifies WASM hashes match at compile time across crates

  5. Version embedding: Embed a version/hash in the contract that can be queried

Impact

Without addressing this systematically:

  • Silent failures when components drift
  • Hard-to-debug "contract not found" errors
  • Production rooms becoming inaccessible after updates

[AI-assisted - Claude]

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions