From 7d4f5598976af7e9b27729cbbba433a6019bbe3f Mon Sep 17 00:00:00 2001 From: Skullcoin <116502774+proofofgame@users.noreply.github.com> Date: Sat, 10 Jan 2026 18:40:04 +0300 Subject: [PATCH 1/7] Create sip-enft-private-layer.md --- sip-enft-private-layer.md | 197 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 197 insertions(+) create mode 100644 sip-enft-private-layer.md diff --git a/sip-enft-private-layer.md b/sip-enft-private-layer.md new file mode 100644 index 00000000..b3048ce2 --- /dev/null +++ b/sip-enft-private-layer.md @@ -0,0 +1,197 @@ +# SIP-XXX: Encrypted NFTs - Standard Trait for Commitment-Based Private Layers (eNFT) + +## Preamble + +- **SIP**: SIP-XXX +- **Title**: Encrypted NFTs - Standard Trait for Commitment-Based Private Layers (eNFT) +- **Authors**: Xenitron nortinex@gmail.com +- **Status**: Draft +- **Consideration**: Technical +- **Type**: Standard +- **Layer**: Traits +- **Created**: 2026-01-10 +- **License**: CC0-1.0 +- **Sign-off**: +- **Discussions-To**: https://forum.stacks.org/t/encrypted-nfts-on-stacks-a-standard-trait-for-commitment-based-private-layers-enft/18560 + +# Abstract + +This SIP proposes a simple, composable trait for “Encrypted NFTs” (eNFTs): NFTs that commit on-chain to a private off-chain payload (a “private layer”) while keeping the payload itself off-chain. The standard defines (1) a public commitment interface, (2) an optional owner-gated envelope descriptor for wallet UX, and (3) indexer-friendly event conventions. This enables interoperable private-layer NFT patterns across contracts, wallets, marketplaces, and indexers without requiring consensus changes. + +# Copyright + +This SIP is made available under the terms of the CC0-1.0 license. +This SIP’s copyright is waived to the extent possible under law. + +# Introduction + +Today, “private layer / encrypted metadata” NFTs on Stacks are implemented as bespoke, project-specific patterns. That fragmentation makes it hard for wallets, marketplaces, and indexers to support them generically. + +This SIP standardizes a minimal interface for eNFT private layers: +- A **public commitment** (hash) to the private payload, enabling anyone to verify integrity after reveal. +- An optional **owner-gated envelope descriptor** to guide wallet UX (e.g., show “Reveal” only to the owner). +- A recommended **event format** so indexers can discover updates efficiently. + +## Goals + +- Define a reusable trait for commitment-based private layers for NFTs. +- Make private-layer patterns discoverable and composable for wallets/indexers. +- Keep the standard minimal and non-consensus. + +## Non-Goals + +- Full on-chain confidentiality (not achievable in a public read-only model). +- Mandating a specific storage network, encryption scheme, or reveal flow. +- Defining a full game/puzzle “answer verification” protocol (out of scope). + +# Specification + +## 1. Terminology + +- **Payload**: The private off-chain data (JSON, image, encrypted blob, etc.). +- **Commitment**: A hash over the payload (or ciphertext) recorded on-chain. +- **Envelope**: A small off-chain descriptor used for UX/access, e.g., a retrieval URI, encrypted key, or signed URL. +- **Reveal**: Off-chain delivery of payload/envelope to the user; verification is done by comparing hash(payload) to on-chain commitment. + +## 2. Commitment Semantics + +Implementations MUST expose a 32-byte commitment for a given token-id. +The commitment MUST be computed using the declared algorithm identifier. + +This SIP does not mandate a single algorithm, but RECOMMENDS: +- `algo = u0` => SHA-256 over raw payload bytes + +## 3. Trait Interface (Clarity) + +The trait defines two read-only methods: one public (commitment) and one optional/UX-oriented (owner envelope). + +### 3.1 Clarity trait definition + +```clarity +(define-trait enft-private-layer-trait + ( + ;; Public: returns the commitment to the private payload (or ciphertext) + (get-private-commitment (uint) + (response + (tuple + (commitment (buff 32)) ;; hash of payload or ciphertext + (algo uint) ;; algorithm id (e.g., u0 = sha256) + (mime (optional (string-ascii 64))) ;; e.g. "application/json", "image/png" + (size (optional uint)) ;; bytes (optional) + (commitment-version uint) ;; scheme versioning + ) + uint + ) + ) + + ;; UX-oriented: returns an owner-gated envelope descriptor. + ;; Implementations SHOULD check ownership for consistent wallet UX. + (get-owner-envelope (uint) + (response + (tuple + (envelope-uri (string-ascii 256)) ;; retrieval location (NOT a secrecy guarantee) + (envelope-hash (buff 32)) ;; integrity check for envelope blob/response + (algo uint) ;; algorithm id for envelope-hash + (envelope-version uint) ;; scheme versioning + ) + uint + ) + ) + ) +) +``` + +## 3.2 Error Codes (Recommended) +Implementations MAY choose their own error codes. This SIP RECOMMENDS: + +`err u404` => token-id not found / no private layer set + +`err u100` => not authorized (e.g., tx-sender not owner) for get-owner-envelope + +## 4. Events (Indexer Conventions) +When a private-layer commitment is set or updated, contracts SHOULD emit a print event with a predictable structure: + +```clarity + +(print { + notification: "enft-update", + token-id: token-id, + commitment: commitment, + algo: algo, + commitment-version: commitment-version +}) +``` + +If an envelope descriptor is set/updated, contracts MAY emit: + +```clarity + +(print { + notification: "enft-envelope-update", + token-id: token-id, + envelope-hash: envelope-hash, + algo: algo, + envelope-version: envelope-version +}) +``` + +Notes: + +- Events are intended for indexers/wallets discovery and UI updates. + +- `envelope-uri` SHOULD NOT be treated as confidential by default. + +## Backwards Compatibility +This SIP is additive and does not break existing SIP-009 NFT contracts. Projects can implement this trait alongside existing token URI metadata patterns. Wallets/indexers can support eNFTs incrementally. + +## Security Considerations +**Read-only visibility and “owner gating”** + +`get-owner-envelope` ownership checks are primarily for **wallet UX consistency**, not cryptographic secrecy. Read-only calls can be simulated by node operators; therefore, **confidentiality MUST NOT rely solely on on-chain gating**. + +If the envelope or payload must remain private, it SHOULD be protected off-chain via: + +- encryption (e.g., encrypt payload/key per owner), and/or + +- access control (signed messages, bearer tokens, short TTL URLs). + +**Integrity and server non-equivocation** + +The on-chain commitment ensures the server cannot swap the underlying private payload after minting without being detected. Clients MUST verify `hash(payload)==commitment` after reveal. + +**Phishing / malicious URIs** + +Wallets SHOULD treat envelope URIs as untrusted input and apply standard URL safety practices. + +## Reference Implementation + +A reference contract (informative) can implement: + +- storage mapping token-id => commitment tuple + +- storage mapping token-id => envelope tuple + +- setters restricted to contract-defined roles (e.g., token owner or game operator) + +- `print` events as specified above + +## Related Work + +Cryptographic commitments (hash commitments) and commit–reveal mechanics are widely used across blockchains and in on-chain games to prevent equivocation. Separately, some NFT ecosystems support “encrypted metadata” or off-chain private content patterns, but these are typically application-specific and lack a shared interface for wallets/indexers. +To the best of our knowledge, Stacks currently has no minimal, interoperable trait + event convention that standardizes a commitment-anchored private layer for SIP-009 NFTs. This SIP fills that gap by defining a composable trait and predictable indexer events, while remaining non-consensus and implementation-agnostic. + +## Activation + +No consensus changes are required. Adoption is voluntary: + +- NFT contracts implement the trait + +- wallets/indexers add UI for commitments and optional reveal flows + +- marketplaces may display “private layer present” and verified reveal status + +## References + +[1] SIP-009 (NFT trait standard on Stacks) + +[2] Forum discussion thread linked in Preamble From 84fafd0ec0c8a614fc152d6a3b59d76b2f259c8c Mon Sep 17 00:00:00 2001 From: Skullcoin Labs <116502774+proofofgame@users.noreply.github.com> Date: Sun, 18 Jan 2026 02:07:49 +0300 Subject: [PATCH 2/7] Update sip-enft-private-layer.md --- sip-enft-private-layer.md | 189 ++++++++++++++++++++++++-------------- 1 file changed, 121 insertions(+), 68 deletions(-) diff --git a/sip-enft-private-layer.md b/sip-enft-private-layer.md index b3048ce2..31968cde 100644 --- a/sip-enft-private-layer.md +++ b/sip-enft-private-layer.md @@ -1,14 +1,13 @@ -# SIP-XXX: Encrypted NFTs - Standard Trait for Commitment-Based Private Layers (eNFT) +# SIP-XXX: Standard Trait Definition for Commitment-Based Private Metadata (Encrypted NFTs) ## Preamble - **SIP**: SIP-XXX -- **Title**: Encrypted NFTs - Standard Trait for Commitment-Based Private Layers (eNFT) +- **Title**: Standard Trait Definition for Commitment-Based Private Metadata (Encrypted NFTs) - **Authors**: Xenitron nortinex@gmail.com - **Status**: Draft - **Consideration**: Technical - **Type**: Standard -- **Layer**: Traits - **Created**: 2026-01-10 - **License**: CC0-1.0 - **Sign-off**: @@ -16,27 +15,40 @@ # Abstract -This SIP proposes a simple, composable trait for “Encrypted NFTs” (eNFTs): NFTs that commit on-chain to a private off-chain payload (a “private layer”) while keeping the payload itself off-chain. The standard defines (1) a public commitment interface, (2) an optional owner-gated envelope descriptor for wallet UX, and (3) indexer-friendly event conventions. This enables interoperable private-layer NFT patterns across contracts, wallets, marketplaces, and indexers without requiring consensus changes. +This SIP proposes a minimal, composable trait interface for “Encrypted NFTs” (eNFTs): NFTs that commit on-chain to a private off-chain payload (“private metadata”) while keeping the payload itself off-chain. The standard defines: + +1) a public commitment interface, +2) an optional owner-gated envelope descriptor for wallet User Experience, and +3) indexer-friendly event conventions. + +This enables interoperable private-metadata NFT patterns across contracts, wallets, marketplaces, and indexers without requiring consensus changes. + # Copyright This SIP is made available under the terms of the CC0-1.0 license. This SIP’s copyright is waived to the extent possible under law. -# Introduction -Today, “private layer / encrypted metadata” NFTs on Stacks are implemented as bespoke, project-specific patterns. That fragmentation makes it hard for wallets, marketplaces, and indexers to support them generically. +## Introduction + +“Encrypted metadata / private metadata” NFTs on Stacks are currently implemented as project-specific patterns. This fragmentation makes it difficult for wallets, marketplaces, and indexers to support such NFTs uniformly. + +This SIP standardizes a minimal interface for commitment-based private metadata on SIP-009 NFTs: -This SIP standardizes a minimal interface for eNFT private layers: -- A **public commitment** (hash) to the private payload, enabling anyone to verify integrity after reveal. -- An optional **owner-gated envelope descriptor** to guide wallet UX (e.g., show “Reveal” only to the owner). -- A recommended **event format** so indexers can discover updates efficiently. +- A **public commitment** (hash) to the payload (or ciphertext), enabling anyone to verify integrity after reveal. +- An optional **owner-gated envelope descriptor** to guide wallet User Experience (e.g., show “Reveal” only to the owner). +- A recommended **event format** so indexers can detect updates efficiently. + +### Relationship to SIP-009 + +This trait is designed to be implemented **alongside** SIP-009-compliant NFT contracts, not as a replacement. An eNFT contract implements SIP-009 for ownership and transfer, and additionally implements this trait to expose commitment-based private metadata. ## Goals -- Define a reusable trait for commitment-based private layers for NFTs. +- Define a reusable trait for commitment-based private metadata for eNFTs. - Make private-layer patterns discoverable and composable for wallets/indexers. -- Keep the standard minimal and non-consensus. +- Keep the standard minimal, additive, and backward-compatible. ## Non-Goals @@ -49,42 +61,72 @@ This SIP standardizes a minimal interface for eNFT private layers: ## 1. Terminology - **Payload**: The private off-chain data (JSON, image, encrypted blob, etc.). -- **Commitment**: A hash over the payload (or ciphertext) recorded on-chain. -- **Envelope**: A small off-chain descriptor used for UX/access, e.g., a retrieval URI, encrypted key, or signed URL. -- **Reveal**: Off-chain delivery of payload/envelope to the user; verification is done by comparing hash(payload) to on-chain commitment. +- **Ciphertext**: An encrypted payload (still considered “payload bytes” for commitment purposes). +- **Commitment**: A hash over the payload bytes (often ciphertext bytes) recorded on-chain. +- **Envelope**: A small off-chain descriptor used for UX/access (e.g., retrieval URI, encrypted key blob, signed URL descriptor). +- **Reveal**: Off-chain delivery of payload/envelope to the user; the client verifies integrity by comparing hash(payload_bytes) to the on-chain commitment. +- **Algo ID**: An integer identifier that indicates how the commitment hash is computed. +- **Scheme Version**: A monotonically increasing version number for commitment/envelope encoding. -## 2. Commitment Semantics +### 2. Commitment Semantics -Implementations MUST expose a 32-byte commitment for a given token-id. -The commitment MUST be computed using the declared algorithm identifier. +Implementations **MUST** expose a commitment for a given token-id. -This SIP does not mandate a single algorithm, but RECOMMENDS: +- The commitment **MUST** be computed exactly according to the declared algorithm id. +- The commitment **MUST** be stable: the same payload bytes must produce the same commitment. +- This SIP does not mandate a single algorithm, but **RECOMMENDS**: - `algo = u0` => SHA-256 over raw payload bytes -## 3. Trait Interface (Clarity) +### Algorithm Registry (Informative) + +| Algo ID | Algorithm | Notes | +|---------|-----------|-------| +| u0 | SHA-256 | Recommended default | +| u1-u99 | Reserved | For future standardization | +| u100+ | Application-defined | Projects may define custom algorithms | + +**Notes** +- If the payload is JSON, implementers should treat the committed object as raw bytes of a canonical encoding chosen by the application (this SIP does not standardize canonicalization). Consumers must verify against the exact bytes they receive on reveal. -The trait defines two read-only methods: one public (commitment) and one optional/UX-oriented (owner envelope). +--- -### 3.1 Clarity trait definition +### 3. Trait Interface (Clarity) + +To make “optional” functionality actually optional in Clarity, this SIP defines **two traits**: + +- A **required** commitment trait (baseline interoperability). +- An **optional** owner-envelope trait (wallet UX extension). + +Contracts may implement the baseline trait alone, or both traits. + +#### 3.1 Required Trait: Commitment ```clarity -(define-trait enft-private-layer-trait +(define-trait enft-commitment-trait ( - ;; Public: returns the commitment to the private payload (or ciphertext) + ;; Public: returns the commitment to the private payload (often ciphertext bytes) (get-private-commitment (uint) (response (tuple - (commitment (buff 32)) ;; hash of payload or ciphertext + (commitment (buff 32)) ;; hash of payload bytes (algo uint) ;; algorithm id (e.g., u0 = sha256) (mime (optional (string-ascii 64))) ;; e.g. "application/json", "image/png" - (size (optional uint)) ;; bytes (optional) - (commitment-version uint) ;; scheme versioning + (size (optional uint)) ;; payload size in bytes (optional) + (commitment-version uint) ;; commitment scheme version ) uint ) ) + ) +) +``` + +#### 3.2 Optional Trait: Owner-Gated Envelope (Wallet UX Extension) - ;; UX-oriented: returns an owner-gated envelope descriptor. +```clarity +(define-trait enft-owner-envelope-trait + ( + ;; User Experience oriented: returns an owner-gated envelope descriptor. ;; Implementations SHOULD check ownership for consistent wallet UX. (get-owner-envelope (uint) (response @@ -92,7 +134,7 @@ The trait defines two read-only methods: one public (commitment) and one optiona (envelope-uri (string-ascii 256)) ;; retrieval location (NOT a secrecy guarantee) (envelope-hash (buff 32)) ;; integrity check for envelope blob/response (algo uint) ;; algorithm id for envelope-hash - (envelope-version uint) ;; scheme versioning + (envelope-version uint) ;; envelope scheme version ) uint ) @@ -101,18 +143,26 @@ The trait defines two read-only methods: one public (commitment) and one optiona ) ``` -## 3.2 Error Codes (Recommended) -Implementations MAY choose their own error codes. This SIP RECOMMENDS: +**Normative guidance** +- Contracts that claim eNFT support **MUST** implement `enft-commitment-trait`. +- Contracts **MAY** implement `enft-owner-envelope-trait` to provide a standardized “Reveal” UX path. +- Wallets/indexers should treat the presence of `enft-owner-envelope-trait` as an optional capability. -`err u404` => token-id not found / no private layer set +--- -`err u100` => not authorized (e.g., tx-sender not owner) for get-owner-envelope +### 3.3 Error Codes (Recommended) -## 4. Events (Indexer Conventions) -When a private-layer commitment is set or updated, contracts SHOULD emit a print event with a predictable structure: +Implementations **MAY** choose their own error codes. This SIP **RECOMMENDS**: -```clarity +- `err u404` => token-id not found / no commitment set +- `err u100` => not authorized for `get-owner-envelope` (only relevant if `enft-owner-envelope-trait` is implemented) + + +### 4. Events (Indexer Conventions) +When a private-metadata commitment is set or updated, contracts **SHOULD** emit a `print` event with a predictable structure: + +```clarity (print { notification: "enft-update", token-id: token-id, @@ -122,10 +172,9 @@ When a private-layer commitment is set or updated, contracts SHOULD emit a print }) ``` -If an envelope descriptor is set/updated, contracts MAY emit: +If an envelope descriptor is set/updated, contracts **MAY** emit: ```clarity - (print { notification: "enft-envelope-update", token-id: token-id, @@ -135,63 +184,67 @@ If an envelope descriptor is set/updated, contracts MAY emit: }) ``` -Notes: - +**Notes** - Events are intended for indexers/wallets discovery and UI updates. +- `envelope-uri` is intentionally excluded from the event for safety; wallets should fetch it via the read-only function if needed. +- Indexers should treat these events as hints and verify by reading the latest on-chain state as required. -- `envelope-uri` SHOULD NOT be treated as confidential by default. +--- ## Backwards Compatibility -This SIP is additive and does not break existing SIP-009 NFT contracts. Projects can implement this trait alongside existing token URI metadata patterns. Wallets/indexers can support eNFTs incrementally. + +This SIP is additive and does not break existing SIP-009 NFT contracts. Projects can implement these traits alongside existing token URI / metadata patterns. Wallets and indexers can support eNFTs incrementally. + +--- ## Security Considerations -**Read-only visibility and “owner gating”** +### Read-only visibility and “owner gating” `get-owner-envelope` ownership checks are primarily for **wallet UX consistency**, not cryptographic secrecy. Read-only calls can be simulated by node operators; therefore, **confidentiality MUST NOT rely solely on on-chain gating**. -If the envelope or payload must remain private, it SHOULD be protected off-chain via: - +If the envelope or payload must remain private, it **SHOULD** be protected off-chain via: - encryption (e.g., encrypt payload/key per owner), and/or +- access control (signed challenges, bearer tokens, short-TTL URLs). -- access control (signed messages, bearer tokens, short TTL URLs). - -**Integrity and server non-equivocation** +### Integrity and server non-equivocation +The on-chain commitment ensures the content provider cannot swap the underlying payload after minting (or after a commitment update) without being detected. Clients **MUST** verify `hash(payload_bytes) == commitment` after reveal. -The on-chain commitment ensures the server cannot swap the underlying private payload after minting without being detected. Clients MUST verify `hash(payload)==commitment` after reveal. +### Phishing / malicious URIs +Wallets should treat envelope URIs as untrusted input and apply standard URL safety practices (origin warnings, link previews sandboxing, and user confirmation flows where appropriate). -**Phishing / malicious URIs** +--- -Wallets SHOULD treat envelope URIs as untrusted input and apply standard URL safety practices. +## Reference Implementation (Informative) -## Reference Implementation - -A reference contract (informative) can implement: - -- storage mapping token-id => commitment tuple +A reference contract can implement: +- a mapping `token-id -> commitment tuple` +- optionally a mapping `token-id -> envelope tuple` +- setters restricted to contract-defined roles (e.g., token owner or authorized operator) +- `print` events as specified above -- storage mapping token-id => envelope tuple +--- -- setters restricted to contract-defined roles (e.g., token owner or game operator) +## Related Work (Informative) -- `print` events as specified above +Commitments and commit–reveal schemes are widely used across blockchains to prevent equivocation. Some NFT ecosystems support “encrypted metadata” patterns, but these are often application-specific and lack a shared interface for wallets/indexers. -## Related Work +To the best of our knowledge, Stacks lacks a minimal, interoperable trait and event convention for commitment-anchored private metadata on SIP-009 NFTs; this SIP defines such a standard in a composable, non-consensus, and implementation-agnostic manner. -Cryptographic commitments (hash commitments) and commit–reveal mechanics are widely used across blockchains and in on-chain games to prevent equivocation. Separately, some NFT ecosystems support “encrypted metadata” or off-chain private content patterns, but these are typically application-specific and lack a shared interface for wallets/indexers. -To the best of our knowledge, Stacks currently has no minimal, interoperable trait + event convention that standardizes a commitment-anchored private layer for SIP-009 NFTs. This SIP fills that gap by defining a composable trait and predictable indexer events, while remaining non-consensus and implementation-agnostic. +--- ## Activation -No consensus changes are required. Adoption is voluntary: +This SIP defines a voluntary standard trait and does not require a consensus upgrade. -- NFT contracts implement the trait +The SIP is considered **“Active”** when: -- wallets/indexers add UI for commitments and optional reveal flows +1) A reference implementation is deployed on Stacks mainnet (maintained by the SIP authors or any party), and +2) At least one independent integration demonstrates interoperability (e.g., an indexer parses the events, or a wallet/marketplace displays the commitment and/or envelope capability). -- marketplaces may display “private layer present” and verified reveal status +Until then, the SIP remains **“Draft”**, and implementers may ship experimental contracts under the proposed interface. ## References -[1] SIP-009 (NFT trait standard on Stacks) +[1] [SIP-009 ](https://github.com/stacksgov/sips/blob/main/sips/sip-009/sip-009-nft-standard.md) -[2] Forum discussion thread linked in Preamble +[2] [Forum discussion thread](https://forum.stacks.org/t/encrypted-nfts-on-stacks-a-standard-trait-for-commitment-based-private-layers-enft/18560) From 03c2a106288ad97f66fe304eb4f9debc4ea60e30 Mon Sep 17 00:00:00 2001 From: Skullcoin Labs <116502774+proofofgame@users.noreply.github.com> Date: Fri, 30 Jan 2026 14:38:01 +0300 Subject: [PATCH 3/7] Improve clarity in notes and security considerations Clarified notes on events and updated security considerations regarding read-only visibility and owner gating. --- sip-enft-private-layer.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sip-enft-private-layer.md b/sip-enft-private-layer.md index 31968cde..669eb886 100644 --- a/sip-enft-private-layer.md +++ b/sip-enft-private-layer.md @@ -185,7 +185,7 @@ If an envelope descriptor is set/updated, contracts **MAY** emit: ``` **Notes** -- Events are intended for indexers/wallets discovery and UI updates. +- Events are intended for indexers/wallets discovery and user interface updates. - `envelope-uri` is intentionally excluded from the event for safety; wallets should fetch it via the read-only function if needed. - Indexers should treat these events as hints and verify by reading the latest on-chain state as required. @@ -200,7 +200,7 @@ This SIP is additive and does not break existing SIP-009 NFT contracts. Projects ## Security Considerations ### Read-only visibility and “owner gating” -`get-owner-envelope` ownership checks are primarily for **wallet UX consistency**, not cryptographic secrecy. Read-only calls can be simulated by node operators; therefore, **confidentiality MUST NOT rely solely on on-chain gating**. +`get-owner-envelope` ownership checks are primarily for **wallet UX consistency**, not cryptographic secrecy. Read-only calls can be simulated by any party running a node; therefore, **confidentiality MUST NOT rely solely on on-chain gating**. If the envelope or payload must remain private, it **SHOULD** be protected off-chain via: - encryption (e.g., encrypt payload/key per owner), and/or From 86b7a24412fbb58e8453dcc64ce815610f88dbc1 Mon Sep 17 00:00:00 2001 From: Skullcoin Labs <116502774+proofofgame@users.noreply.github.com> Date: Sun, 15 Feb 2026 21:27:48 +0300 Subject: [PATCH 4/7] Move SIP-038 to standard folder structure Move SIP-038 to standard folder structure, address all reviewer feedback --- sips/sip-038/sip-enft-private-layer.md | 261 +++++++++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100644 sips/sip-038/sip-enft-private-layer.md diff --git a/sips/sip-038/sip-enft-private-layer.md b/sips/sip-038/sip-enft-private-layer.md new file mode 100644 index 00000000..fec3c8e6 --- /dev/null +++ b/sips/sip-038/sip-enft-private-layer.md @@ -0,0 +1,261 @@ +# SIP-038: Standard Trait Definition for Commitment-Based Private Metadata (Encrypted NFTs) + +## Preamble + +SIP Number: 038 +Title: Standard Trait Definition for Commitment-Based Private Metadata (Encrypted NFTs) +Authors: Xenitron nortinex@gmail.com, Bogachev ogres2009anton@gmail.com +Status: Draft +Consideration: Technical +Type: Standard +Created: 2026-01-10 +License: CC0-1.0 +Sign-off: +Discussions-To: https://forum.stacks.org/t/encrypted-nfts-on-stacks-a-standard-trait-for-commitment-based-private-layers-enft/18560 + +# Abstract + +This SIP proposes a minimal, composable trait interface for “Encrypted NFTs” (eNFTs): NFTs that commit on-chain to a private off-chain payload (“private metadata”) while keeping the payload itself off-chain. The standard defines: + +1) a public commitment interface, +2) an optional owner-gated envelope descriptor for wallet User Experience, and +3) indexer-friendly event conventions. + +This enables interoperable private-metadata NFT patterns across contracts, wallets, marketplaces, and indexers without requiring consensus changes. + + +# Copyright + +This SIP is made available under the terms of the CC0-1.0 license. +This SIP’s copyright is waived to the extent possible under law. + + +## Introduction + +“Encrypted metadata / private metadata” NFTs on Stacks are currently implemented as project-specific patterns. This fragmentation makes it difficult for wallets, marketplaces, and indexers to support such NFTs uniformly. + +This SIP standardizes a minimal interface for commitment-based private metadata on SIP-009 NFTs: + +- A **public commitment** (hash) to the payload (or ciphertext), enabling anyone to verify integrity after reveal. +- An optional **owner-gated envelope descriptor** to guide wallet User Experience (e.g., show “Reveal” only to the owner). +- A recommended **event format** so indexers can detect updates efficiently. + +### Relationship to SIP-009 + +This trait is designed to be implemented **alongside** SIP-009-compliant NFT contracts, not as a replacement. An eNFT contract implements SIP-009 for ownership and transfer, and additionally implements this trait to expose commitment-based private metadata. + +## Goals + +- Define a reusable trait for commitment-based private metadata for eNFTs. +- Make private-layer patterns discoverable and composable for wallets/indexers. +- Keep the standard minimal, additive, and backward-compatible. + +## Non-Goals + +- Full on-chain confidentiality (not achievable in a public read-only model). +- Mandating a specific storage network, encryption scheme, or reveal flow. +- Defining a full game/puzzle “answer verification” protocol (out of scope). + +# Specification + +## 1. Terminology + +- **Payload**: The private off-chain data (JSON, image, encrypted blob, etc.). +- **Ciphertext**: An encrypted payload (still considered “payload bytes” for commitment purposes). +- **Commitment**: A hash over the payload bytes (often ciphertext bytes) recorded on-chain. +- **Envelope**: A small off-chain descriptor used for UX/access (e.g., retrieval URI, encrypted key blob, signed URL descriptor). +- **Reveal**: Off-chain delivery of payload/envelope to the user; the client verifies integrity by comparing hash(payload_bytes) to the on-chain commitment. +- **Algo ID**: An integer identifier that indicates how the commitment hash is computed. +- **Scheme Version**: A monotonically increasing version number for commitment/envelope encoding. + +### 2. Commitment Semantics + +Implementations **must** expose a commitment for a given token-id. + +- The commitment **must** be computed exactly according to the declared algorithm id. +- The commitment **must** be stable: the same payload bytes must produce the same commitment. +- This SIP does not mandate a single algorithm, but **recommends**: +- `algo = u0` => SHA-256 over raw payload bytes + +### Algorithm Registry (Informative) + +| Algo ID | Algorithm | Notes | +|---------|-----------|-------| +| u0 | SHA-256 | Recommended default | +| u1-u99 | Reserved | For future standardization | +| u100+ | Application-defined | Projects may define custom algorithms | + +**Notes** +- If the payload is JSON, implementers should treat the committed object as raw bytes of a canonical encoding chosen by the application (this SIP does not standardize canonicalization). Consumers must verify against the exact bytes they receive on reveal. + +--- + +### 3. Trait Interface (Clarity) + +To make “optional” functionality actually optional in Clarity, this SIP defines **two traits**: + +- A **required** commitment trait (baseline interoperability). +- An **optional** owner-envelope trait (wallet UX extension). + +Contracts may implement the baseline trait alone, or both traits. + +#### 3.1 Required Trait: Commitment + +```clarity +(define-trait enft-commitment-trait + ( + ;; Public: returns the commitment to the private payload (often ciphertext bytes) + (get-private-commitment (uint) + (response + (tuple + (commitment (buff 32)) ;; hash of payload bytes + (algo uint) ;; algorithm id (e.g., u0 = sha256) + (mime (optional (string-ascii 64))) ;; e.g. "application/json", "image/png" + (size (optional uint)) ;; payload size in bytes (optional) + (commitment-version uint) ;; commitment scheme version + ) + uint + ) + ) + ) +) +``` + +#### 3.2 Optional Trait: Owner-Gated Envelope (Wallet UX Extension) + +```clarity +(define-trait enft-owner-envelope-trait + ( + ;; User Experience oriented: returns an owner-gated envelope descriptor. + ;; Implementations SHOULD check ownership for consistent wallet UX. + (get-owner-envelope (uint) + (response + (tuple + (envelope-uri (string-ascii 256)) ;; retrieval location (NOT a secrecy guarantee) + (envelope-hash (buff 32)) ;; integrity check for envelope blob/response + (algo uint) ;; algorithm id for envelope-hash + (envelope-version uint) ;; envelope scheme version + ) + uint + ) + ) + ) +) +``` + +**Normative guidance** +- Contracts that claim eNFT support **must** implement `enft-commitment-trait`. +- Contracts **may** implement `enft-owner-envelope-trait` to provide a standardized “Reveal” UX path. +- Wallets/indexers should treat the presence of `enft-owner-envelope-trait` as an optional capability. + +--- + +### 3.3 Error Codes (Recommended) + +Implementations **may** choose their own error codes. This SIP **recommends**: + +- `err u404` => token-id not found / no commitment set +- `err u100` => not authorized for `get-owner-envelope` (only relevant if `enft-owner-envelope-trait` is implemented) + + +### 4. Events (Indexer Conventions) + +When a private-metadata commitment is set or updated, contracts **should** emit a `print` event with a predictable structure: + +```clarity +(print { + notification: "enft-update", + token-id: token-id, + commitment: commitment, + algo: algo, + commitment-version: commitment-version +}) +``` + +If an envelope descriptor is set/updated, contracts **may** emit: + +```clarity +(print { + notification: "enft-envelope-update", + token-id: token-id, + envelope-hash: envelope-hash, + algo: algo, + envelope-version: envelope-version +}) +``` + +**Notes** +- Events are intended for indexers/wallets discovery and user interface updates. +- `envelope-uri` is intentionally excluded from the event for safety; wallets should fetch it via the read-only function if needed. +- Indexers should treat these events as hints and verify by reading the latest on-chain state as required. + +--- + +## Backwards Compatibility + +This SIP introduces no breaking changes. It is additive and does not modify existing SIP-009 NFT contracts. Projects can implement these traits alongside existing token URI / metadata patterns. Wallets and indexers can support eNFTs incrementally. + +--- + +## Security Considerations + +### Read-only visibility and “owner gating” +`get-owner-envelope` ownership checks are primarily for **wallet UX consistency**, not cryptographic secrecy. Read-only calls can be simulated by any party running a node; therefore, **confidentiality must not rely solely on on-chain gating**. + +If the envelope or payload must remain private, it **should** be protected off-chain via: +- encryption (e.g., encrypt payload/key per owner), and/or +- access control (signed challenges, bearer tokens, short-TTL URLs). + +### Integrity and server non-equivocation +Assuming collision-resistant hash functions, the on-chain commitment ensures the server cannot swap the underlying private payload after minting without being detected. Clients **must** verify `hash(payload_bytes) == commitment` after reveal. + +### Phishing / malicious URIs +Wallets should treat envelope URIs as untrusted input and apply standard URL safety practices (origin warnings, link previews sandboxing, and user confirmation flows where appropriate). + +--- + +## Reference Implementation (Informative) + +A reference contract can implement: +- a mapping `token-id -> commitment tuple` +- optionally a mapping `token-id -> envelope tuple` +- setters restricted to contract-defined roles (e.g., token owner or authorized operator) +- `print` events as specified above + +--- + +## Related Work (Informative) + +Commitments and commit–reveal schemes are widely used across blockchains to prevent equivocation. Some NFT ecosystems support “encrypted metadata” patterns, but these are often application-specific and lack a shared interface for wallets/indexers. + +To the best of our knowledge, Stacks lacks a minimal, interoperable trait and event convention for commitment-anchored private metadata on SIP-009 NFTs; this SIP defines such a standard in a composable, non-consensus, and implementation-agnostic manner. + +--- + +## Activation + +No consensus changes are required. This SIP is considered +Active when all of the following conditions are met before +Bitcoin block height (H₀ + 12,960), where H₀ is the Bitcoin +block height at the time this SIP is merged, and 12,960 blocks +represents approximately 3 months: + +1) A reference trait contract implementing this specification is deployed on Stacks mainnet. + +2) At least one production NFT contract on mainnet implements the trait(s) exactly as specified in this SIP. + +3) At least one ecosystem integration — indexer, wallet, or marketplace — demonstrates consumption of the interface, + proving interoperability independent of the authors. + +A trait that follows this specification will be made available +on mainnet upon ratification, and its deployed address will be +recorded here. + +Until activation, the SIP remains Draft, and implementers may +ship experimental contracts under the proposed interface. + +## References + +[1] [SIP-009 ](https://github.com/stacksgov/sips/blob/main/sips/sip-009/sip-009-nft-standard.md) + +[2] [Forum discussion thread](https://forum.stacks.org/t/encrypted-nfts-on-stacks-a-standard-trait-for-commitment-based-private-layers-enft/18560) From d4a17cddaf5954996b2b8fadddb0ddc7b75373f5 Mon Sep 17 00:00:00 2001 From: Skullcoin Labs <116502774+proofofgame@users.noreply.github.com> Date: Sun, 15 Feb 2026 21:33:22 +0300 Subject: [PATCH 5/7] Remove old file location (moved to sips/sip-038/) --- sip-enft-private-layer.md | 250 -------------------------------------- 1 file changed, 250 deletions(-) delete mode 100644 sip-enft-private-layer.md diff --git a/sip-enft-private-layer.md b/sip-enft-private-layer.md deleted file mode 100644 index 669eb886..00000000 --- a/sip-enft-private-layer.md +++ /dev/null @@ -1,250 +0,0 @@ -# SIP-XXX: Standard Trait Definition for Commitment-Based Private Metadata (Encrypted NFTs) - -## Preamble - -- **SIP**: SIP-XXX -- **Title**: Standard Trait Definition for Commitment-Based Private Metadata (Encrypted NFTs) -- **Authors**: Xenitron nortinex@gmail.com -- **Status**: Draft -- **Consideration**: Technical -- **Type**: Standard -- **Created**: 2026-01-10 -- **License**: CC0-1.0 -- **Sign-off**: -- **Discussions-To**: https://forum.stacks.org/t/encrypted-nfts-on-stacks-a-standard-trait-for-commitment-based-private-layers-enft/18560 - -# Abstract - -This SIP proposes a minimal, composable trait interface for “Encrypted NFTs” (eNFTs): NFTs that commit on-chain to a private off-chain payload (“private metadata”) while keeping the payload itself off-chain. The standard defines: - -1) a public commitment interface, -2) an optional owner-gated envelope descriptor for wallet User Experience, and -3) indexer-friendly event conventions. - -This enables interoperable private-metadata NFT patterns across contracts, wallets, marketplaces, and indexers without requiring consensus changes. - - -# Copyright - -This SIP is made available under the terms of the CC0-1.0 license. -This SIP’s copyright is waived to the extent possible under law. - - -## Introduction - -“Encrypted metadata / private metadata” NFTs on Stacks are currently implemented as project-specific patterns. This fragmentation makes it difficult for wallets, marketplaces, and indexers to support such NFTs uniformly. - -This SIP standardizes a minimal interface for commitment-based private metadata on SIP-009 NFTs: - -- A **public commitment** (hash) to the payload (or ciphertext), enabling anyone to verify integrity after reveal. -- An optional **owner-gated envelope descriptor** to guide wallet User Experience (e.g., show “Reveal” only to the owner). -- A recommended **event format** so indexers can detect updates efficiently. - -### Relationship to SIP-009 - -This trait is designed to be implemented **alongside** SIP-009-compliant NFT contracts, not as a replacement. An eNFT contract implements SIP-009 for ownership and transfer, and additionally implements this trait to expose commitment-based private metadata. - -## Goals - -- Define a reusable trait for commitment-based private metadata for eNFTs. -- Make private-layer patterns discoverable and composable for wallets/indexers. -- Keep the standard minimal, additive, and backward-compatible. - -## Non-Goals - -- Full on-chain confidentiality (not achievable in a public read-only model). -- Mandating a specific storage network, encryption scheme, or reveal flow. -- Defining a full game/puzzle “answer verification” protocol (out of scope). - -# Specification - -## 1. Terminology - -- **Payload**: The private off-chain data (JSON, image, encrypted blob, etc.). -- **Ciphertext**: An encrypted payload (still considered “payload bytes” for commitment purposes). -- **Commitment**: A hash over the payload bytes (often ciphertext bytes) recorded on-chain. -- **Envelope**: A small off-chain descriptor used for UX/access (e.g., retrieval URI, encrypted key blob, signed URL descriptor). -- **Reveal**: Off-chain delivery of payload/envelope to the user; the client verifies integrity by comparing hash(payload_bytes) to the on-chain commitment. -- **Algo ID**: An integer identifier that indicates how the commitment hash is computed. -- **Scheme Version**: A monotonically increasing version number for commitment/envelope encoding. - -### 2. Commitment Semantics - -Implementations **MUST** expose a commitment for a given token-id. - -- The commitment **MUST** be computed exactly according to the declared algorithm id. -- The commitment **MUST** be stable: the same payload bytes must produce the same commitment. -- This SIP does not mandate a single algorithm, but **RECOMMENDS**: -- `algo = u0` => SHA-256 over raw payload bytes - -### Algorithm Registry (Informative) - -| Algo ID | Algorithm | Notes | -|---------|-----------|-------| -| u0 | SHA-256 | Recommended default | -| u1-u99 | Reserved | For future standardization | -| u100+ | Application-defined | Projects may define custom algorithms | - -**Notes** -- If the payload is JSON, implementers should treat the committed object as raw bytes of a canonical encoding chosen by the application (this SIP does not standardize canonicalization). Consumers must verify against the exact bytes they receive on reveal. - ---- - -### 3. Trait Interface (Clarity) - -To make “optional” functionality actually optional in Clarity, this SIP defines **two traits**: - -- A **required** commitment trait (baseline interoperability). -- An **optional** owner-envelope trait (wallet UX extension). - -Contracts may implement the baseline trait alone, or both traits. - -#### 3.1 Required Trait: Commitment - -```clarity -(define-trait enft-commitment-trait - ( - ;; Public: returns the commitment to the private payload (often ciphertext bytes) - (get-private-commitment (uint) - (response - (tuple - (commitment (buff 32)) ;; hash of payload bytes - (algo uint) ;; algorithm id (e.g., u0 = sha256) - (mime (optional (string-ascii 64))) ;; e.g. "application/json", "image/png" - (size (optional uint)) ;; payload size in bytes (optional) - (commitment-version uint) ;; commitment scheme version - ) - uint - ) - ) - ) -) -``` - -#### 3.2 Optional Trait: Owner-Gated Envelope (Wallet UX Extension) - -```clarity -(define-trait enft-owner-envelope-trait - ( - ;; User Experience oriented: returns an owner-gated envelope descriptor. - ;; Implementations SHOULD check ownership for consistent wallet UX. - (get-owner-envelope (uint) - (response - (tuple - (envelope-uri (string-ascii 256)) ;; retrieval location (NOT a secrecy guarantee) - (envelope-hash (buff 32)) ;; integrity check for envelope blob/response - (algo uint) ;; algorithm id for envelope-hash - (envelope-version uint) ;; envelope scheme version - ) - uint - ) - ) - ) -) -``` - -**Normative guidance** -- Contracts that claim eNFT support **MUST** implement `enft-commitment-trait`. -- Contracts **MAY** implement `enft-owner-envelope-trait` to provide a standardized “Reveal” UX path. -- Wallets/indexers should treat the presence of `enft-owner-envelope-trait` as an optional capability. - ---- - -### 3.3 Error Codes (Recommended) - -Implementations **MAY** choose their own error codes. This SIP **RECOMMENDS**: - -- `err u404` => token-id not found / no commitment set -- `err u100` => not authorized for `get-owner-envelope` (only relevant if `enft-owner-envelope-trait` is implemented) - - -### 4. Events (Indexer Conventions) - -When a private-metadata commitment is set or updated, contracts **SHOULD** emit a `print` event with a predictable structure: - -```clarity -(print { - notification: "enft-update", - token-id: token-id, - commitment: commitment, - algo: algo, - commitment-version: commitment-version -}) -``` - -If an envelope descriptor is set/updated, contracts **MAY** emit: - -```clarity -(print { - notification: "enft-envelope-update", - token-id: token-id, - envelope-hash: envelope-hash, - algo: algo, - envelope-version: envelope-version -}) -``` - -**Notes** -- Events are intended for indexers/wallets discovery and user interface updates. -- `envelope-uri` is intentionally excluded from the event for safety; wallets should fetch it via the read-only function if needed. -- Indexers should treat these events as hints and verify by reading the latest on-chain state as required. - ---- - -## Backwards Compatibility - -This SIP is additive and does not break existing SIP-009 NFT contracts. Projects can implement these traits alongside existing token URI / metadata patterns. Wallets and indexers can support eNFTs incrementally. - ---- - -## Security Considerations - -### Read-only visibility and “owner gating” -`get-owner-envelope` ownership checks are primarily for **wallet UX consistency**, not cryptographic secrecy. Read-only calls can be simulated by any party running a node; therefore, **confidentiality MUST NOT rely solely on on-chain gating**. - -If the envelope or payload must remain private, it **SHOULD** be protected off-chain via: -- encryption (e.g., encrypt payload/key per owner), and/or -- access control (signed challenges, bearer tokens, short-TTL URLs). - -### Integrity and server non-equivocation -The on-chain commitment ensures the content provider cannot swap the underlying payload after minting (or after a commitment update) without being detected. Clients **MUST** verify `hash(payload_bytes) == commitment` after reveal. - -### Phishing / malicious URIs -Wallets should treat envelope URIs as untrusted input and apply standard URL safety practices (origin warnings, link previews sandboxing, and user confirmation flows where appropriate). - ---- - -## Reference Implementation (Informative) - -A reference contract can implement: -- a mapping `token-id -> commitment tuple` -- optionally a mapping `token-id -> envelope tuple` -- setters restricted to contract-defined roles (e.g., token owner or authorized operator) -- `print` events as specified above - ---- - -## Related Work (Informative) - -Commitments and commit–reveal schemes are widely used across blockchains to prevent equivocation. Some NFT ecosystems support “encrypted metadata” patterns, but these are often application-specific and lack a shared interface for wallets/indexers. - -To the best of our knowledge, Stacks lacks a minimal, interoperable trait and event convention for commitment-anchored private metadata on SIP-009 NFTs; this SIP defines such a standard in a composable, non-consensus, and implementation-agnostic manner. - ---- - -## Activation - -This SIP defines a voluntary standard trait and does not require a consensus upgrade. - -The SIP is considered **“Active”** when: - -1) A reference implementation is deployed on Stacks mainnet (maintained by the SIP authors or any party), and -2) At least one independent integration demonstrates interoperability (e.g., an indexer parses the events, or a wallet/marketplace displays the commitment and/or envelope capability). - -Until then, the SIP remains **“Draft”**, and implementers may ship experimental contracts under the proposed interface. - -## References - -[1] [SIP-009 ](https://github.com/stacksgov/sips/blob/main/sips/sip-009/sip-009-nft-standard.md) - -[2] [Forum discussion thread](https://forum.stacks.org/t/encrypted-nfts-on-stacks-a-standard-trait-for-commitment-based-private-layers-enft/18560) From 2fb59ab314557d6076b5fb65b7ca9d5577249992 Mon Sep 17 00:00:00 2001 From: Skullcoin Labs <116502774+proofofgame@users.noreply.github.com> Date: Tue, 24 Feb 2026 18:34:35 +0300 Subject: [PATCH 6/7] Revise terminology and enhance user experience guidance Updated terminology and clarified user experience guidance in the SIP for Encrypted NFTs. Added notes on encryption flexibility and MIME type validation. --- sips/sip-038/sip-enft-private-layer.md | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/sips/sip-038/sip-enft-private-layer.md b/sips/sip-038/sip-enft-private-layer.md index fec3c8e6..2239ccbf 100644 --- a/sips/sip-038/sip-enft-private-layer.md +++ b/sips/sip-038/sip-enft-private-layer.md @@ -11,15 +11,16 @@ Type: Standard Created: 2026-01-10 License: CC0-1.0 Sign-off: +Layer: Trait Discussions-To: https://forum.stacks.org/t/encrypted-nfts-on-stacks-a-standard-trait-for-commitment-based-private-layers-enft/18560 # Abstract This SIP proposes a minimal, composable trait interface for “Encrypted NFTs” (eNFTs): NFTs that commit on-chain to a private off-chain payload (“private metadata”) while keeping the payload itself off-chain. The standard defines: -1) a public commitment interface, -2) an optional owner-gated envelope descriptor for wallet User Experience, and -3) indexer-friendly event conventions. +1) A public commitment interface, +2) An optional owner-gated envelope descriptor for wallet user experience. +3) Indexer-friendly event conventions. This enables interoperable private-metadata NFT patterns across contracts, wallets, marketplaces, and indexers without requiring consensus changes. @@ -37,7 +38,7 @@ This SIP’s copyright is waived to the extent possible under law. This SIP standardizes a minimal interface for commitment-based private metadata on SIP-009 NFTs: - A **public commitment** (hash) to the payload (or ciphertext), enabling anyone to verify integrity after reveal. -- An optional **owner-gated envelope descriptor** to guide wallet User Experience (e.g., show “Reveal” only to the owner). +- An optional **owner-gated envelope descriptor** to guide wallet user experience (e.g., show “Reveal” only to the owner). - A recommended **event format** so indexers can detect updates efficiently. ### Relationship to SIP-009 @@ -56,6 +57,8 @@ This trait is designed to be implemented **alongside** SIP-009-compliant NFT con - Mandating a specific storage network, encryption scheme, or reveal flow. - Defining a full game/puzzle “answer verification” protocol (out of scope). +**Note on encryption flexibility:** This SIP intentionally does not mandate a specific encryption scheme. Wallets and indexers interact only with the commitment layer — they verify `hash(payload) == on-chain commitment` and never perform decryption. Decryption occurs off-chain between the application and the asset owner, outside the trait scope. Different projects require different threat models (server-assisted reveal vs. client-side decryption with embedded key blob vs. proxy re-encryption). To prevent fragmentation, implementers using any non-default algorithm id (other than `u0`) **must** publish a stable, publicly available algorithm specification. Wallets **may** support only `u0` (SHA-256) and treat unknown algorithm ids as unsupported for verification while still supporting discovery. + # Specification ## 1. Terminology @@ -66,7 +69,8 @@ This trait is designed to be implemented **alongside** SIP-009-compliant NFT con - **Envelope**: A small off-chain descriptor used for UX/access (e.g., retrieval URI, encrypted key blob, signed URL descriptor). - **Reveal**: Off-chain delivery of payload/envelope to the user; the client verifies integrity by comparing hash(payload_bytes) to the on-chain commitment. - **Algo ID**: An integer identifier that indicates how the commitment hash is computed. -- **Scheme Version**: A monotonically increasing version number for commitment/envelope encoding. +- **Version**: A monotonically increasing version number for commitment/envelope encoding. +- **Token-id**: The SIP-009 NFT token identifier (`uint`). Each token-id uniquely identifies a single NFT within a contract. ### 2. Commitment Semantics @@ -85,6 +89,8 @@ Implementations **must** expose a commitment for a given token-id. | u1-u99 | Reserved | For future standardization | | u100+ | Application-defined | Projects may define custom algorithms | +**Wallet implementation guidance:** Wallets and indexers are not required to support all algorithm ids. A conforming wallet may support only `u0` (SHA-256) and display a warning or informational notice for tokens using unrecognized algorithms. The registry enables organic ecosystem convergence without requiring a new SIP for each algorithm. + **Notes** - If the payload is JSON, implementers should treat the committed object as raw bytes of a canonical encoding chosen by the application (this SIP does not standardize canonicalization). Consumers must verify against the exact bytes they receive on reveal. @@ -126,7 +132,7 @@ Contracts may implement the baseline trait alone, or both traits. ```clarity (define-trait enft-owner-envelope-trait ( - ;; User Experience oriented: returns an owner-gated envelope descriptor. + ;; user experience oriented: returns an owner-gated envelope descriptor. ;; Implementations SHOULD check ownership for consistent wallet UX. (get-owner-envelope (uint) (response @@ -155,7 +161,7 @@ Contracts may implement the baseline trait alone, or both traits. Implementations **may** choose their own error codes. This SIP **recommends**: - `err u404` => token-id not found / no commitment set -- `err u100` => not authorized for `get-owner-envelope` (only relevant if `enft-owner-envelope-trait` is implemented) +- `err u401` => not authorized for `get-owner-envelope` (only relevant if `enft-owner-envelope-trait` is implemented) ### 4. Events (Indexer Conventions) @@ -212,6 +218,9 @@ Assuming collision-resistant hash functions, the on-chain commitment ensures the ### Phishing / malicious URIs Wallets should treat envelope URIs as untrusted input and apply standard URL safety practices (origin warnings, link previews sandboxing, and user confirmation flows where appropriate). +### MIME type validation +The `mime` field is informational and does not instruct clients to execute content. Clients **should** validate MIME types before processing payloads and **should** reject executable types (e.g., `application/x-executable`, `application/x-msdownload`) by default. This follows standard content-security practices. + --- ## Reference Implementation (Informative) @@ -248,7 +257,7 @@ represents approximately 3 months: proving interoperability independent of the authors. A trait that follows this specification will be made available -on mainnet upon ratification, and its deployed address will be +on mainnet upon status update to activation-in-progress, and its deployed address will be recorded here. Until activation, the SIP remains Draft, and implementers may From 602f055eae314ff1b5dfaef01528da5fe66c07b5 Mon Sep 17 00:00:00 2001 From: "Claire Gadd (Topalian)" <118488201+clairetopalian@users.noreply.github.com> Date: Tue, 10 Mar 2026 12:10:16 -0600 Subject: [PATCH 7/7] Changing status from 'draft' to accepted' --- sips/sip-038/sip-enft-private-layer.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sips/sip-038/sip-enft-private-layer.md b/sips/sip-038/sip-enft-private-layer.md index 2239ccbf..fab349f1 100644 --- a/sips/sip-038/sip-enft-private-layer.md +++ b/sips/sip-038/sip-enft-private-layer.md @@ -5,7 +5,7 @@ SIP Number: 038 Title: Standard Trait Definition for Commitment-Based Private Metadata (Encrypted NFTs) Authors: Xenitron nortinex@gmail.com, Bogachev ogres2009anton@gmail.com -Status: Draft +Status: Accepted Consideration: Technical Type: Standard Created: 2026-01-10