Skip to content

SDK: ForeignChainSignatureVerifier doesn't record the payload version it was built with #4078

Description

@netrome

Background

ForeignChainSignatureVerifier derives borsh serialization so consumer contracts can persist it between submitting verify_foreign_transaction and verifying the response in the callback (added deliberately for the bridge team in #2266, closing #2263).

However, the verifier does not record which payload version it was built against. build() pins payload_version (from DEFAULT_PAYLOAD_VERSION) into the on-chain request, while verify_signature() re-derives the expected payload hash from the crate-global DEFAULT_PAYLOAD_VERSION at verify time.

Failure scenario

  1. A consumer contract builds a request with SDK version X (DEFAULT_PAYLOAD_VERSION = V1) and persists the verifier in its state.
  2. The consumer upgrades to SDK version Y where the default moved to V2.
  3. The persisted verifier now recomputes a V2 hash for a request that was bound to V1, and rejects a valid response.

Surfaced by review on #4032 (which added ForeignTxSignPayload::new(version, ...), making the fix straightforward).

Proposed fix

Store the payload version on the verifier at build time and derive the expected hash from self.payload_version in verify_signature().

Timing constraint

Adding a field changes the verifier's borsh layout, which breaks deserialization of any already-persisted verifier (loudly: consumer state reads panic). Today no end-to-end foreign-tx flow is live, so nothing real can be persisted yet — the change is free now and becomes a consumer-breaking change once integrations ship. This should land before the foreign-tx feature/SDK gets real consumers.

Additional consideration

While changing the layout anyway, consider wrapping the persisted verifier in a versioned enum (e.g. V1 { ... }) so future field additions are non-breaking instead of hitting this same cliff.

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