URN 1.1: chain identity without coin type, optional wallet domain#1
Merged
Conversation
… domain
The chain identity is now the (nt, ci) pair, mirroring the go-mhda
reference: chain::str()/key() serialize nt:<network>:ci:<chain_id> only,
equality compares network and chain id, and the constructor drops the
coin-type argument. The SLIP-44 coin type becomes optional metadata on
chain (coin() -> std::optional, set_coin/clear_coin); the ct component is
accepted anywhere on input, re-emitted in decimal right after ci, and an
empty set_coin_type clears it.
chain::from_key is canonical-only: the accepted input must be the exact
nt:<network>:ci:<chain_id> rendering, with surrounding ASCII whitespace
trimmed and tolerated. A key carrying ct (the pre-1.1 key format) fails
with the new error_code::coin_type_in_chain_key so legacy keys fail
loudly instead of being silently reinterpreted; any other known
component, unknown tokens, reordering or non-canonical spelling fails
with the new error_code::invalid_chain_key. error_code::missing_coin_type
is removed; ct is never required. chain::from_nss stays lenient.
Harden parsing and mutation against malformed values:
- ct parses as plain decimal or 0x/0X-prefixed hex only; 0o/0b prefixes,
digit-group underscores, signs and a bare 0x are rejected, and a
leading zero stays decimal (060 == 60, never octal).
- Every NSS value must be printable ASCII (0x21-0x7E) after ASCII-only
trimming; control bytes, interior whitespace and non-ASCII bytes
(including Unicode spaces) are rejected instead of silently normalised.
- The free-form setters (set_address_prefix/suffix, set_wallet_type/id)
and the address constructor params reject NSS-corrupting values (':',
'?', '#', anything outside printable ASCII) with the new
error_code::invalid_value; an empty value still resets the field.
New optional wallet domain on address: free-form wt (wallet type) and wi
(wallet instance id) components, each independently optional, emitted
last in the canonical NSS and orthogonal to strict validation.
Network-type values are renamed to the commonly accepted network names
(bitcoin, avalanche, tron, solana, xrpl, stellar, aptos, cardano,
algorand) with no aliases for the old short forms; constant identifiers
are unchanged. The coin registry fixes ATOM to 118 (168 belongs to
Helleniccoin), adds 34 SLIP-44 entries and is reordered ascending.
Version 1.1.0. SPEC.md and README are brought in lockstep with the Go
reference; tests mirror the Go fixtures (wallet-domain suite, strict
chain-key suite, optional-ct semantics, post-review hardening suite,
recomputed hash vectors) — 139 cases, green under ASan/UBSan/LSan and
the full warning set, with byte-for-byte parity against the Go
implementation on the shared corpus.
x88
force-pushed
the
feat/urn-1.1-chain-identity
branch
from
July 4, 2026 10:01
898725d to
3d0219b
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Version 1.1.0 — a behavioral mirror of the go-mhda 1.1 grammar rework. The URN stays bit-for-bit compatible between both implementations.
What changes
(nt, ci).chain::str()/chain::key()emitnt:<network>:ci:<chain_id>;operator==compares the identity only; the constructor ischain(network_type, chain_id). The SLIP-44 coin type becomes optional metadata (std::optional<coin_type>viacoin()/set_coin()/clear_coin()), parsed from any position and emitted afterciin decimal — never part of the key.chain::from_key. A chain key must be the canonical identity string.ctin a key (the pre-1.1 format) throws the dedicatederror_code::coin_type_in_chain_key; any other residue — known non-identity components, unknown tokens, reordering, non-canonical case — throwserror_code::invalid_chain_key.chain::from_nssstays lenient for extraction from full NSS forms.wt(client type:web3,metamask,tonconnect, …) andwi(wallet instance id: UUID, HD root fingerprint, …), emitted last in the canonical order, orthogonal to validation.bitcoin,tron,avalanche,solana,xrpl,stellar,aptos,cardano,algorand);evm,cosmos,near,sui,tonunchanged; no aliases.atomfixed to 118 per SLIP-44 (168 is Helleniccoin), 34 modern entries added, list reordered ascending.ctnumeric grammar (decimal /0xhex only); validated free-form setters and constructor params — a value able to smuggle:,?,#or whitespace into the NSS throws the newerror_code::invalid_value.Versioning note: the previous release shipped as tag v1.0.0 while its in-tree markers still read 0.1.0; this release restores consistency (CMake project version, changelog and README all say 1.1.0).
Testing
-Wall -Wextra -Wpedantic -Wshadow -Wconversion -Wsign-conversion -Werror, and again under-fsanitize=address,undefined,leakwithhalt_on_error=1— zero diagnostics.