Overview
The Meta-Address Registry contract (identipay::meta_address_registry) implements identiPay’s stealth identity system. It maps human-readable names (like “@alice.idpay”) to cryptographic public keys for stealth address derivation.
Key Properties:
- Names resolve to public keys only, never to Sui addresses
- One government credential can register exactly one name (anti-sybil)
- Names are permanent but keys can be rotated
- Registration requires a ZK proof of credential ownership
Source Code
Location:contracts/sources/meta_address_registry.move:10
How It Works
Credential Commitment
User computes identity commitment
C = Poseidon(credential_fields) from their government ID.ZK Proof Generation
User generates a proof that C is backed by a valid credential without revealing the credential.
Name Registration
User submits name, public keys, commitment, and ZK proof. Contract verifies and registers the name.
Anti-Sybil Enforcement
The commitment is permanently bound to the name. Same credential cannot register another name.
Data Structures
MetaAddressRegistry
Shared registry mapping names to stealth meta-addresses.Sui object identifier
Maps name to MetaAddressEntry object ID (for ownership tracking)
Maps name to public keys (for direct on-chain resolution)
Maps identity commitment to name (anti-sybil: one credential = one name)
MetaAddress
On-chain lookup record storing the public keys needed for stealth address derivation.Ed25519 spending public key (32 bytes) for address derivation
X25519 viewing public key (32 bytes) for payment detection
MetaAddressEntry
Owned object representing a registered name. Held by the registrant for key rotation.Sui object identifier
The registered name (e.g., “alice”)
Ed25519 spending public key (32 bytes)
X25519 viewing public key (32 bytes)
Poseidon hash of credential fields (anti-sybil binding)
Registration timestamp (epoch ms)
Events
NameRegistered
Emitted when a name is successfully registered.Registered name
Ed25519 spending public key
X25519 viewing public key
Identity commitment hash
KeysRotated
Emitted when keys are rotated.Name whose keys were rotated
New spending public key
New viewing public key
Entry Functions
register_name
Register a new name with stealth meta-address. Requires ZK proof of credential ownership. Function Signature:Mutable reference to the meta-address registry
ZK verification key for identity registration circuit
Name to register (3-20 chars, lowercase alphanumeric + hyphens)
Ed25519 spending public key (exactly 32 bytes)
X25519 viewing public key (exactly 32 bytes)
Poseidon(credential_fields) commitment
Groth16 proof bytes
Public inputs: [identity_commitment]
EInvalidNameLength(2): Name is < 3 or > 20 charactersEInvalidNameCharacter(3): Name contains invalid characters or starts/ends with hyphenEInvalidSpendPubkeyLength(4): Spend pubkey is not 32 bytesEInvalidViewPubkeyLength(5): View pubkey is not 32 bytesEEmptyIdentityCommitment(6): Identity commitment is emptyENameAlreadyTaken(0): Name already registeredECommitmentAlreadyRegistered(1): This credential already registered a different nameEProofVerificationFailed(7): ZK proof is invalid
meta_address_registry.move:112-164
Example:
rotate_keys
Rotate keys for a registered name. Requires ZK proof binding to the same identity commitment. Function Signature:Mutable reference to the registry
Mutable reference to the owned entry (caller must own this)
ZK verification key
New Ed25519 spending public key (32 bytes)
New X25519 viewing public key (32 bytes)
Groth16 proof bytes
Public inputs: [identity_commitment] (must match entry.identity_commitment)
EInvalidSpendPubkeyLength(4): New spend pubkey is not 32 bytesEInvalidViewPubkeyLength(5): New view pubkey is not 32 bytesEProofVerificationFailed(7): ZK proof is invalid
meta_address_registry.move:169-199
Example:
Public Functions
resolve_name
Resolve a name to its meta-address (spend + view public keys). Primary lookup function.Reference to the registry
Name to resolve
Ed25519 spending public key (32 bytes)
X25519 viewing public key (32 bytes)
ENameNotFound(8): Name is not registered
meta_address_registry.move:208-212
Example:
resolve_entry
Resolve from an owned MetaAddressEntry object directly.meta_address_registry.move:216-218
name_exists
Check if a name is registered.meta_address_registry.move:221-223
commitment_exists
Check if an identity commitment is already registered.meta_address_registry.move:226-228
MetaAddressEntry Accessors
meta_address_registry.move:232-236
Name Validation
Names must follow these rules:- Length: 3-20 characters
- Characters: Lowercase a-z, digits 0-9, hyphens
- Format: Cannot start or end with hyphen
alicebob-smithuser123coffee-shop-sf
ab(too short)Alice(uppercase)-alice(starts with hyphen)alice-(ends with hyphen)alice_bob(underscore not allowed)
meta_address_registry.move:242-261
Anti-Sybil Mechanism
One Credential, One Name
One Credential, One Name
Each identity commitment can only register one name. This prevents users with a single government ID from squatting multiple names.
Commitment Permanence
Commitment Permanence
The commitment-to-name binding is permanent. Even after key rotation, the same commitment remains bound to the same name.
ZK Privacy
ZK Privacy
The ZK proof reveals only that the user has a valid credential, not the credential details (name, DOB, etc.).
No Name Transfers
No Name Transfers
Names cannot be transferred or sold. The MetaAddressEntry object is owned by the registrant and cannot change hands.
Stealth Address Derivation
The registry enables stealth addresses per the Dual-Key Stealth Address Protocol (DKSAP):- Sender resolves recipient’s name to
(K_spend, K_view) - Sender generates ephemeral keypair
(r, R = r*G) - Sender computes shared secret
S = r * K_view - Sender derives stealth address
P = K_spend + Hash(S)*G - Sender sends payment to
Pand emits announcement withR - Recipient scans announcements, computes
S = k_view * R - Recipient checks if
P == K_spend + Hash(S)*G - Recipient derives private key
p = k_spend + Hash(S)
Security Considerations
View Key Separation: The view key can safely be shared with third parties (like exchanges) for payment detection without granting spend authority.
On-Chain Resolution: Name resolution happens entirely on-chain with no external dependencies, ensuring censorship resistance and availability.
Related Modules
Announcements
Stealth payment detection events
ZK Verifier
Groth16 proof verification for identity
Settlement
Uses stealth addresses for receipt delivery
