Skip to content
This repository was archived by the owner on Jul 10, 2026. It is now read-only.
This repository was archived by the owner on Jul 10, 2026. It is now read-only.

Synapse.body_hash is a constant when required_hash_fields is empty (the default), so the integrity check is a no-op #3407

Description

@loom-agent

Problem

Synapse.required_hash_fields defaults to () (bittensor/core/synapse.py). body_hash returns get_hash("".join(hashes)), and when required_hash_fields is empty, hashes stays [], so body_hash is get_hash("") - a constant independent of the body. Any Synapse subclass that does not set required_hash_fields therefore has a no-op integrity check: completely different payloads produce the same computed_body_hash.

Verified on staging (Python 3.12, bittensor 10.5.0)

class A(Synapse): name: str; data: str   # required_hash_fields stays () (default)
A(name='route1', data='alpha').body_hash
  -> a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a
A(name='route2', data='TOTALLY DIFFERENT BODY CONTENT 12345').body_hash
  -> a7ffc6f8bf1ed76651c14756a061d662f580ff4de43b49fa82d80a4b80f8434a   # IDENTICAL
# once required_hash_fields = ('data',) is set, the hashes differ (integrity works)

(a7ffc6f8... is the SHA3-256 of the empty string.)

Why not a simple PR

Hashing-all-fields-when-empty is wire-incompatible: a new dendrite that hashes the full body would no longer match an old axon that hashes the empty string, so every mixed-version request would be rejected. The only wire-safe code change is emitting a runtime warning when required_hash_fields is empty, which does not close the hole. That is why I am opening this for design rather than sending a patch.

Suggested direction (for discussion)

A versioned body-hash header (e.g. body_hash_v2 computed over the full serialized body), negotiated by protocol/feature version, so new<->new traffic gets real integrity while new<->old keeps the current (empty) behaviour. Optional interim hardening: warn loudly when a Synapse used for signing has an empty required_hash_fields.

Related prior work on required_hash_fields (all closed) addressed adding/using the field, not this empty-default fail-open.

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