Skip to content

Expose parent hash on the Config::Header trait (parent_hash()) #2242

Description

@kunal171

Summary

The Config::Header trait only exposes number(). There's no way to read a
header's parent hash generically over T::Header — it's only available as a
public field on the concrete SubstrateHeader. I'd like to propose adding a
parent_hash() accessor (plus an associated hash type) to the trait.

What I was building / why I hit this

I'm building a Rust, code-first Substrate indexer framework on top of subxt
(kunal171/subdex). To stay reorg-safe,
the indexer validates chain continuity by comparing each incoming block's
parent_hash against the hash it stored for the previous height; on a mismatch it
rolls back and re-syncs the corrected chain.

I wanted the ingestion layer to be generic over subxt::Config (so it works for
any chain): client.blocks() → block.header() → T::Header. But:

fn parent_of<T: subxt::Config>(h: &T::Header) -> ??? {
    // not possible — Header only exposes number()
}

The only workaround is to abandon the generic abstraction and hard-code a concrete
config (e.g. PolkadotConfig) so I can touch SubstrateHeader's parent_hash
field directly — which defeats the purpose of Config being generic and is awkward
for any tool that wants to support arbitrary chains.

Current state

pub trait Header: Sized + Encode + Decode + Debug + Sync + Send + DeserializeOwned + Clone {
    fn number(&self) -> u64;
}

number() is exposed, but parent_hash (which every Substrate header carries,
right next to the number) is not.

Proposed change

Add an associated hash type + accessor:

pub trait Header: ... {
    type Hash: Hash;
    fn number(&self) -> u64;
    fn parent_hash(&self) -> Self::Hash;
}

implemented for SubstrateHeader<H> as type Hash = H, returning the existing
field (Hash already requires Copy, so it's a by-value return).

This is a breaking trait change (external Header impls would need to add the
associated type + method), but it's small and SubstrateHeader is the only in-repo
implementor. I'm also open to alternatives — e.g. tying the hash type to
Config::Hasher instead of a new associated type — whichever you prefer.

Status

I have a working implementation that passes cargo check --workspace --exclude test-runtime and cargo test -p subxt --lib (30 passed). The only failing doctest
(runtime_path field in subxt/src/lib.rs) fails identically on current master,
so it's pre-existing and unrelated.

Happy to open a PR shortly once there's agreement on the API shape. Would a
contribution along these lines be welcome?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

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