Skip to content

Allow genesis hash prefixes as the network in Concordium DIDs - #986

Merged
andynelson merged 2 commits into
mainfrom
feature/did-genesis-network
Nov 12, 2026
Merged

andynelson merged 2 commits into
mainfrom
feature/did-genesis-network

Conversation

@andynelson

@andynelson andynelson commented Nov 10, 2026 •

Copy link
Copy Markdown
Contributor

Purpose

Chain IDs can already name a Concordium network in two ways, ccd:testnet or ccd:<first 32 hex chars of the genesis hash>. DIDs only accept testnet/mainnet, so a network without a well-known name can't appear in a DID at all.

This PR lets the network segment of every DID type (acc, cred, sci, pkc, idp, encidcred) be a genesis hash prefix, for example did:ccd:4221332d34e1694168c2a0c0b3fd0f27:idp:0. Any 32-character lowercase hex prefix is accepted; there is no registry.

Changes

  • web3id::did: add GenesisHashPrefix (with TESTNET/MAINNET constants and from_genesis_hash) and a Network::Genesis(GenesisHashPrefix) variant, plus Network::genesis_hash_prefix and Network::same_chain.
  • Network equality, ordering and hashing compare the chain the value refers to. So Network::Testnet == Network::Genesis(GenesisHashPrefix::TESTNET), and the existing network checks in verification (verify_network, the issuer match) accept either form with no call-site changes. For Testnet/Mainnet on their own, behaviour is identical to before; ordering is still Testnet < Mainnet.
  • Serialization keeps the form a value was created with. testnet/mainnet keep their string, JSON and binary (tags 0/1) encodings, so existing proofs, requests and anchors hash and verify exactly as before. The genesis form is written as the 32 hex characters, or as binary tag 2 followed by the 16 prefix bytes.
  • The DID parser rejects malformed prefixes (wrong length, uppercase hex) instead of falling back to "no network means mainnet".

Effect on code that matches on Network

Network gains a Genesis variant and is marked #[non_exhaustive]. Code outside this crate that matches on Network variant by variant, like this:

match network {
    Network::Testnet => …,
    Network::Mainnet => …,
}

will no longer compile and needs a wildcard arm (_ => …). Because of #[non_exhaustive], any future network forms won't require that again.

Code that only passes Network values around or compares them (==, !=) is unaffected. Comparisons now match by chain, so they accept either form automatically. I found no variant-by-variant matches in this repo, in the JS SDK's Rust bindings, or in concordium-rust-sdk, which only passes the value through and compares it. So I don't expect this to affect anyone in practice and haven't proposed a version bump; the CHANGELOG entry describes the change for anyone who does match on it.

Compatibility notes

Wallets, verifiers and indexers on an older concordium-base will reject did:ccd:<prefix> DIDs and binary tag 2. The genesis form should therefore be adopted per integration once counterparties have upgraded, not used as a default.

Testing

  • cargo test --workspace --all-features passes. Existing test vectors are unchanged.
  • New tests in did.rs: string/JSON round trips for every form, binary encodings (including that tags 0/1 are byte-for-byte unchanged), chain equality including HashSet lookups, every DID type with a genesis prefix, and rejection of malformed prefixes.
  • New test in v1/anchor/verify.rs: a presentation proved with testnet DIDs verifies against a verification context given as the testnet genesis prefix, and fails against a different chain.

Related

A companion PR in concordium-node-sdk-js adopts this in the JS SDK, wallet-connectors and verification-web-ui. It depends on this PR and will be opened as a draft.

DIDs can now identify the network by the first 16 bytes of its genesis
block hash, e.g. did:ccd:4221332d34e1694168c2a0c0b3fd0f27:idp:0, matching
ccd:<prefix> chain IDs. This works for any chain, not only testnet and
mainnet.

- Add GenesisHashPrefix and the Network::Genesis variant; mark Network
  #[non_exhaustive].
- Network equality, ordering and hashing compare the chain, so the named
  and genesis forms of the same network are equal and verification accepts
  either.
- Existing string, JSON and binary forms are unchanged; the genesis form
  serializes as 32 lowercase hex characters or tag 2 + 16 bytes.
- The DID parser rejects malformed genesis prefixes instead of reading
  them as a missing network.
@andynelson
andynelson requested review from allanbrondum, limemloh and soerenbf and removed request for allanbrondum November 11, 2026 10:07
@andynelson
andynelson marked this pull request as ready for review November 12, 2026 12:45
@andynelson
andynelson merged commit b50cd56 into main Nov 12, 2026
26 checks passed
@andynelson
andynelson deleted the feature/did-genesis-network branch November 12, 2026 12:46
andynelson added a commit to Concordium/concordium-node-sdk-js that referenced this pull request Nov 12, 2026
Bump concordium-base to main (Concordium/concordium-base#986), which
accepts did:ccd:<genesis hash prefix>:..., and adopt it across the SDK
packages. Existing DIDs, chain IDs and stored settings are
unchanged; the genesis form is opt-in.

- sdk: widen Network to 'Testnet' | 'Mainnet' | GenesisHashPrefix, with
  helpers for DIDs, chain IDs and key derivation (mainnet derives as
  Mainnet, every other network as Testnet); add a DID module that builds
  and parses every Concordium DID type; route the DID classes,
  create*DID helpers and credential metadata parsing through it; compare
  networks by chain when verifying.
- wallet-connectors: opt-in chainIdFormat: 'genesis' / withGenesisChainId
  for ccd:<genesis hash prefix> chain IDs.
- verification-web-ui: accept a custom network ({ chainId,
  walletDeepLinks }), resolve the network in one place, and fix the
  mainnet CryptoX deep-link schemes.
andynelson added a commit to Concordium/concordium-node-sdk-js that referenced this pull request Nov 12, 2026
Bump concordium-base to main (Concordium/concordium-base#986), which
accepts did:ccd:<genesis hash prefix>:..., and adopt it across the SDK
packages. Existing DIDs, chain IDs and stored settings are
unchanged; the genesis form is opt-in.

- sdk: widen Network to 'Testnet' | 'Mainnet' | GenesisHashPrefix.Type;
  add the GenesisHashPrefix module and network helpers (chain IDs,
  chain equality, key derivation: mainnet derives as Mainnet, every other
  network as Testnet); add parseDID/formatDID helpers for every
  Concordium DID type and route the DID classes, create*DID helpers and
  credential metadata parsing through them; compare networks by chain
  when verifying.
- wallet-connectors: opt-in chainIdFormat: 'genesis' / withGenesisChainId
  for ccd:<genesis hash prefix> chain IDs.
- verification-web-ui: accept a custom network ({ chainId,
  walletDeepLinks }), resolve the network in one place, and fix the
  mainnet CryptoX deep-link schemes.
andynelson added a commit to Concordium/concordium-node-sdk-js that referenced this pull request Nov 12, 2026
Bump concordium-base to main (Concordium/concordium-base#986), which
accepts did:ccd:<genesis hash prefix>:..., and adopt it across the SDK
packages. Existing DIDs, chain IDs and stored settings are
unchanged; the genesis form is opt-in.

- sdk: widen Network to 'Testnet' | 'Mainnet' | GenesisHashPrefix.Type;
  add the GenesisHashPrefix module and network helpers (chain IDs,
  chain equality, key derivation: mainnet derives as Mainnet, every other
  network as Testnet); add parseDID/formatDID helpers for every
  Concordium DID type and route the DID classes, create*DID helpers and
  credential metadata parsing through them; compare networks by chain
  when verifying.
- wallet-connectors: opt-in chainIdFormat: 'genesis' / withGenesisChainId
  for ccd:<genesis hash prefix> chain IDs.
- verification-web-ui: accept a custom network ({ chainId,
  walletDeepLinks }), resolve the network in one place, and fix the
  mainnet CryptoX deep-link schemes.
andynelson added a commit to Concordium/concordium-node-sdk-js that referenced this pull request Nov 12, 2026
Bump concordium-base to main (Concordium/concordium-base#986), which
accepts did:ccd:<genesis hash prefix>:..., and adopt it across the SDK
packages. Existing DIDs, chain IDs and stored settings are
unchanged; the genesis form is opt-in.

- sdk: widen Network to 'Testnet' | 'Mainnet' | GenesisHashPrefix.Type;
  add the GenesisHashPrefix module and network helpers (chain IDs,
  chain equality, key derivation: mainnet derives as Mainnet, every other
  network as Testnet); add parseDID/formatDID helpers for every
  Concordium DID type and route the DID classes, create*DID helpers and
  credential metadata parsing through them; compare networks by chain
  when verifying.
- wallet-connectors: opt-in chainIdFormat: 'genesis' / withGenesisChainId
  for ccd:<genesis hash prefix> chain IDs.
- verification-web-ui: accept a custom network ({ chainId,
  walletDeepLinks }), resolve the network in one place, and fix the
  mainnet CryptoX deep-link schemes.
andynelson added a commit to Concordium/concordium-node-sdk-js that referenced this pull request Nov 12, 2026
Bump concordium-base to main (Concordium/concordium-base#986), which
accepts did:ccd:<genesis hash prefix>:..., and adopt it across the SDK
packages. Existing DIDs, chain IDs and stored settings are
unchanged; the genesis form is opt-in.

- sdk: widen Network to 'Testnet' | 'Mainnet' | GenesisHashPrefix.Type;
  add the GenesisHashPrefix module and network helpers (chain IDs,
  chain equality, key derivation: mainnet derives as Mainnet, every other
  network as Testnet); add a ConcordiumDID class covering every
  Concordium DID type and route the DID classes, create*DID helpers and
  credential metadata parsing through it; compare networks by chain
  when verifying.
- wallet-connectors: opt-in chainIdFormat: 'genesis' / withGenesisChainId
  for ccd:<genesis hash prefix> chain IDs.
- verification-web-ui: accept a custom network ({ chainId,
  walletDeepLinks }), resolve the network in one place, and fix the
  mainnet CryptoX deep-link schemes.
andynelson added a commit to Concordium/concordium-node-sdk-js that referenced this pull request Nov 12, 2026
Bump concordium-base to main (Concordium/concordium-base#986), which
accepts did:ccd:<genesis hash prefix>:..., and adopt it across the SDK
packages. Existing DIDs, chain IDs and stored settings are
unchanged; the genesis form is opt-in.

- sdk: widen Network to 'Testnet' | 'Mainnet' | GenesisHashPrefix.Type;
  add the GenesisHashPrefix module and network helpers (chain IDs,
  chain equality, key derivation: mainnet derives as Mainnet, every other
  network as Testnet); add a ConcordiumDID class covering every
  Concordium DID type and route the DID classes, create*DID helpers and
  credential metadata parsing through it; compare networks by chain
  when verifying.
- wallet-connectors: opt-in chainIdFormat: 'genesis' / withGenesisChainId
  for ccd:<genesis hash prefix> chain IDs.
- verification-web-ui: accept a custom network ({ chainId,
  walletDeepLinks }), resolve the network in one place, and fix the
  CryptoX deep-link schemes (mainnet, and Android testnet).
andynelson added a commit to Concordium/concordium-node-sdk-js that referenced this pull request Nov 12, 2026
Bump concordium-base to main (Concordium/concordium-base#986), which
accepts did:ccd:<genesis hash prefix>:..., and adopt it across the SDK
packages. Existing DIDs, chain IDs and stored settings are
unchanged; the genesis form is opt-in.

- sdk: widen Network to 'Testnet' | 'Mainnet' | GenesisHashPrefix.Type;
  add the GenesisHashPrefix module and network helpers (chain IDs,
  chain equality, key derivation: mainnet derives as Mainnet, every other
  network as Testnet); add a ConcordiumDID class covering every
  Concordium DID type and route the DID classes, create*DID helpers and
  credential metadata parsing through it; compare networks by chain
  when verifying.
- wallet-connectors: opt-in chainIdFormat: 'genesis' / withGenesisChainId
  for ccd:<genesis hash prefix> chain IDs.
- verification-web-ui: accept a custom network ({ chainId,
  walletDeepLinks }), resolve the network in one place, and fix the
  CryptoX deep-link schemes (mainnet, and Android testnet).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants