Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

CIP-0048? | NFT metadata references and payloads #249

Closed
wants to merge 37 commits into from
Closed
Changes from all commits
Commits
Show all changes
37 commits
Select commit Hold shift + click to select a range
05f7c34
Introducing CIP-0048? Extended 721 metadata
Jack-0 Apr 21, 2022
01bce73
added forum post
Jack-0 Apr 21, 2022
a2fe0d4
amendments to specification reserved keywords
Jack-0 Apr 21, 2022
c476add
added pseudo code usage example
Jack-0 Apr 21, 2022
3d1b4f4
added external keyword
Jack-0 Apr 21, 2022
c41d545
added external char shortcut
Jack-0 Apr 21, 2022
56bcda6
added comment on references
Jack-0 Apr 21, 2022
07d87d1
proof read changes
Jack-0 Apr 21, 2022
c1988c3
updated CIP-0048.md
Jack-0 Apr 23, 2022
91ce437
updated CIP-0048.md to include fallback option
Jack-0 Apr 23, 2022
2706144
updated CIP-0048.md to include note on duplication
Jack-0 Apr 23, 2022
921e8eb
added a comment on references
Jack-0 Apr 23, 2022
fe506e1
updated CIP-0048.md to use policy and txhash
Jack-0 May 8, 2022
d8d5a30
updated CIP-0048.md grammar
Jack-0 May 8, 2022
2e7420a
Merge branch 'cardano-foundation:master' into master
Jack-0 Aug 27, 2022
827ca7b
refactored CIP48 into two CIPs
Sep 28, 2022
450812c
updated example
Sep 28, 2022
fc06058
CIP48 and CIP49 are seperate CIPs
Oct 2, 2022
6c9bada
reimplemented CIP48 -_-
Oct 2, 2022
2465815
updated CIP48
Oct 2, 2022
594400b
renamed CIP-0048/CIP-0048.md -> CIP-0048/README.md
Oct 2, 2022
aec50fc
updated README.md header
Oct 2, 2022
09b3b10
ammendments
Oct 2, 2022
54b0c63
ammendments
Oct 2, 2022
bc0906a
amendments
Oct 2, 2022
dc16d71
amendments to example
Oct 2, 2022
b7c36ac
merge
Oct 2, 2022
e4a6509
amendments
Oct 2, 2022
2364e8a
amendments
Oct 2, 2022
edf147b
amendments
Oct 2, 2022
4911949
amendments
Oct 2, 2022
b99a0aa
example update
Oct 2, 2022
c0d2aee
updates to handle image tag usage in CIP25
Oct 2, 2022
7bf0859
updates to handle files tag usage in CIP25
Oct 2, 2022
11eedf3
removed files in CIP48
Oct 2, 2022
404279a
behavior duplicated files in CIP25 if multiple refs are defined
Oct 2, 2022
7480cce
noticed txhashes should be an array
Oct 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
249 changes: 249 additions & 0 deletions CIP-0048/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,249 @@
---
CIP: 48?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
CIP: 48?
CIP: 48

Title: 721 References and Payloads
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Title: 721 References and Payloads
Title: NFT metadata references and payloads

For consistency with PR title.

Authors: Jack (ada9000, https://forum.cardano.org/u/jack7e/, @ada9000_ twitter)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Authors: Jack (ada9000, https://forum.cardano.org/u/jack7e/, @ada9000_ twitter)
Authors:
- Jack <[email protected]>

There's no means to embed URLs in header text, which makes social links impossible. Even if getting an anonymous email to use here, we need something that looks like an email address if only so our web site builders work properly. This is always a list even if having only one member.

Comments-URI: https://forum.cardano.org/t/cip-extended-721/
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Comments-URI: https://forum.cardano.org/t/cip-extended-721/
Discussions:
- https://forum.cardano.org/t/cip-extended-721
- https://github.com/cardano-foundation/CIPs/pull/249

Status: Draft
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Status: Draft
Status: Proposed

Type: Informational
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created: 2022-04-22 (updated 2022-09-22)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Created: 2022-04-22 (updated 2022-09-22)
Created: 2022-04-22

Version history strictly follows GitHub, so "updated" dates don't need to be in the header & our collation scripts can't process these because there's no standard form for them. Current consensus is that particular dated versions can be identified using the GitHub commit hash (forming its own version policy).

---

## Important note

This CIP mentions the `ext` json key defined by [CIP49](https://github.com/cardano-foundation/CIPs/pull/343/files) which is an outcome of work on CIP48.
Comment on lines +11 to +13
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This section may be unnecessary if we transition to CIP-88 to support a "signal" that these references are in use.

Comment on lines +11 to +13
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Important note
This CIP mentions the `ext` json key defined by [CIP49](https://github.com/cardano-foundation/CIPs/pull/343/files) which is an outcome of work on CIP48.

My understanding is that bridging this to CIP88 means that the proposal formerly called CIP49 is now deprecated & I've marked it such on #343 - so if you think otherwise be sure to post in that CIP. In any case any "important note" should be removed from here and placed on one of the top level document sections.

Duplicate of https://github.com/cardano-foundation/CIPs/pull/249/files#r1149624522.


# Abstract
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Abstract
## Abstract

H2 section titles make room for an H1 title which will be added programmatically from the title in the preamble. https://github.com/cardano-foundation/CIPs/blob/master/CIP-0001/README.md#structure


- This standard proposes a method to allow NFT assets to reference other onchain data.
- This would allow users of 721 metadata to increase or reduce the amount of data an NFT asset uses.

# Motivation
Copy link
Collaborator

@rphair rphair Apr 18, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Motivation
## Motivation: why is this CIP necessary?

Yes this long pedantic title is to be used by everybody (similarly for Rationale).


- Large token mints that duplicated data could be dramatically reduced in size by pointing to one transaction payload that contains a ‘boilerplate’ structure.
- 16kB is the upper limit of data in each transaction but If a user wanted more there is no alternative than to store that data off-chain using an external service such as ipfs.
- There is no current mechanism to reduce duplicated metadata
- NFT assets are restricted by there own metadata scope, optional references would prevent this restriction
- There is currently no way to reference on chain data stored in a different policy

# Specification
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Specification
## Specification


### **Inside the 721 metadata JSON**

| reserved | description | scope |
| -------- | ------------------------------------------------------ | ------------------------- |
| refs | references tag, defines where to find the onchain data | Inside `<asset_name>` tag |
| p | contains raw data (on chain data). | Inside `<policy_id>` tag |
Comment on lines +28 to +35
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe that we can eliminate both the refs and p definitions within individual token metadata here if we switch to a URI-schema to signal support by way of CIP-88. More details to be shown below.


### **The `refs` tag**

Contains the `name`, `mediaType`, `src` tags (and the optional `type` tag)

- `name` (string) is the references name (similar usage to name in the current `files` tag)
- `mediaType` (string) defines the mime type for the data referenced in `src`
- is a string
- `src` (string array) is an **ordered** array of references.
- The order is that of which the data will be parsed. For example `["1","3","2"]` will result in payload `"1"` being the start of the data, followed by payload `"3"` and ending with payload `"2"`.

### **Optional `type` tag for `refs`**

The default CIP-48 behavior is to assume the assets parent `<policy_id>` contains all the payloads.

Optionally we define `type` and two options `policy` and `txhash`. To allow for non-default behavior

- `policy`
- Defines an external policy (instead of the default behavior of using the parent policy)
- example
```json
"refs": [
{
"name": "...",
"mediaType": "...",
"type": {
"policy": "<some_external_policy>"
}
}
]
```
- `txhash`
- Defines an array of transaction hashes (instead of the default behavior of using the parent policy)
- example
```json
"refs": [
{
"name": "...",
"mediaType": "...",
"type": {
"txhash": ["<mint_txhash>", "<mint_txhash>"]
}
}
]
```
- `txhash` is faster than parsing all transactions in a given policy.
- `txhash` can dramatically reduce onchain data usage if duplicated data is referenced here _(however, the bytes required to define the reference would have to be less than the reference data itself)_
Comment on lines +47 to +82
Copy link
Collaborator

@Crypto2099 Crypto2099 Mar 27, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we presume that the majority of references could be declared at a top-level utilizing CIP-88, this is just some rough thoughts but perhaps we could expand the references "type" to optionally point to another on-chain pointer or to a direct payload.

{
  48: {
    0: '1.0.0', ; Version?
    1: [ ; Array of references
      {
        "name": "referenceA", ; Name of the reference
        "type": "pointer | payload", ; Maybe an enum of accepted options?
        "payload": { ; Example of a direct payload reference
          "mediaType": "text/plain",
          "content": "My Cool NFT Project"
        },
        "payload": { ; Example of a tx pointer reference?
          "type": "tx",
          "content": "[txhash]",
          "context": "metadata" | "datum"
        },
        "payload": { ; Example of a token point reference?
          "type": "token",
          "content": [(policy_id),(asset_id)],
          "context": "metadata" | "datum"
        }
      }
    ]
  }
}


### **The payload `p` tag**

- Defined within the `<policy_id>` scope
- contains payload reference names followed by a string array of payload data
- example
```json
"p":
{
"1": ["1 is a valid payload"],
"payloadA": ["a...64","b...64"], //a string has a max length of 64 characters
"payloadB": ["I'm found by referencing payloadB"],
}
```

## General structure
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## General structure
### General structure


Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It keeps coming up at CIP meetings recently that, since the chain itself stores CBOR (never JSON), that specifications should be written in CDDL. If this is one of those cases where that's not important then @KtorZ will correct me... and also he has offered to help with translating these specs into CDDL.

We also recommend that the schemas be put in separate files: https://github.com/cardano-foundation/CIPs/blob/master/CIP-0001/README.md#repository-organization

```json
{
"721": {
"ext": ["cip48"], // tells 'user' cip48 is in use within the metadata
"<policy_id>": {
"<asset_name>": {
"project": "<string>",
"name": "<string>",
"image": "<ref_name | uri | array>" // image is defined by refs or a uri
// references
"refs": [
{
"name": "<ref_name>",
"mediaType": "text/plain",
"src": ["<payload_id>", "<payload_id>"] // array of required payload ids (ordered)
}
]
},
// payload
"p": {
"<payload_id>": ["<data>", "<data>"], // payload0
"<payload_id>": ["<data>"] // payload1
}
}
}
}
```
Comment on lines +98 to +126
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the best way to embed references in existing metadata structures would be via a structured URI format as defined in the spec. Rather than just using a name and forcing all parsers to scan for references a defined URI schema would make it easier to detect.

URI Format

uriSchema = {
  scheme : string .size (4..64) ; Examples: ar:https://, ipfs:https://, etc
  path * : string .size (1..64) ; Examples: [ar/ipfs hash]
}

Hypothetical CIP-48 URI format:

uriSchema = ["cip48:https://","referenceA"]

In this way a downstream parser may quickly and easily identify a CIP-48-specific reference only on fields that match the format.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@Crypto2099 do I understand correctly, with this new approach, that there would be no need for the corresponding proposal that has long accompanied this one (which details the external metadata references)?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, I believe the OP and myself agree that the ext flag would be made redundant if CIP-88 were implemented as both have the same function of signaling intent to support a further extension to CIP-25.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

great then, I'll remove the Likely Deprecated tag from this CIP and leave it on #343.


## Notes
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
## Notes
### Notes


- CIP25 currently defines a 'required' image tag.
- CIP48 alters the use of image. Requiring the 'user' to first check if the image string matches any reference names. Then to fallback on the default behavior.
- example, in which the image is found by referring to payloads.
```json
{
"image":"myImageNFT"
"refs":[
{
"name": "myImageNFT"
"mediaType":"image/svg+xml;utf8"
"src": ["refToPayloadA", "refToPayloadB"]
}
]
}
```
- The `image` tag can still be used as a thumbnail if required.
- If there are multiple `refs` defined the references that are _NOT_ defined in the `image` tag have the same behavior as the `files` tag currently defined in CIP25

# Example
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Example
### Example


Mint transaction 1

```json
{
"721": {
"ext": ["cip48"],
"0000000000000000000000000000000000000000000000000000000A": {
"NFT0": {
"project": "CIP48 Example",
"name": "NFT0",
// references
"refs": [
{
"name": "NFT0",
"mediaType": "text/plain",
"src": ["0", "2"]
}
]
},
// payload
"p": {
"0": ["Hello"],
"1": ["Goodbye"]
}
}
}
}
```

Mint transaction 2

```json
{
"721": {
"ext": ["cip48"],
"0000000000000000000000000000000000000000000000000000000A": {
"NFT1": {
"project": "CIP48 Example",
"name": "NFT1",
// references
"refs": [
{
"name": "NFT1",
"mediaType": "text/plain",
"src": ["0", "3"]
}
]
},
// payload
"p": {
"2": ["World"],
"3": ["Moon"]
}
}
}
}
```

### Pseudo code walk through using the above example (using default behavior)

1. Find all transactions for the given `<policy_id>`

- `found 2 mint transcations`

2. Check the **ext** tag for **cip48**

- `found cip48` we now know the metadata contains references and payloads

3. Iterate over each transaction. If a payload is found append that to an map or some data structure

- found 4 payloads
- ```js
payloads = { 0: "Hello", 1: "Goodbye", 2: "World", 3: "Moon" };
```

4. Find all `refs` (references) for the `<asset_name>` we use NFT0. Then build the data in the order defined by the `src` array.

- found 2 references
- ```js
nft0_refs = ["0", "2"];
nft0_data = "HelloWorld";
```

5. use the mediaType (mimetype) to determine the data.
- mediaType = "test/plain"
- NFT0 contains text "HelloWorld"

# Backwards compatibility

Handled via the use of the `"ext"` tag defined in CIP-48.

Comment on lines +237 to +240
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Backwards compatibility
Handled via the use of the `"ext"` tag defined in CIP-48.

I think we've established that the tag will not be used, right? However compatibility would be handled is a good item to included in the Rationale section which still needs to be defined below.

# Further considerations

- Later we may want to use different reference types, maybe even plutus contract references. Due to this I have defined the `type` tag inside the `refs` (references) tag.
- `p` is used instead of **payload** to reduce bytes. Specifically `p` is not used within the `<asset_name>` tag therefore readability is less of a priority than data size. Unlike `refs` which is defined in the `<asset_name>` tag
- JSON is kept over CBOR or alternatives as this CIP is encapsulated in the 721 metadatum tag and JSON is easier for developers to adopt

### Duplicate data

There could be issues with duplicate payloads. To solve the payload defined in the most recently minted tx takes priority.
Comment on lines +241 to +249
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
# Further considerations
- Later we may want to use different reference types, maybe even plutus contract references. Due to this I have defined the `type` tag inside the `refs` (references) tag.
- `p` is used instead of **payload** to reduce bytes. Specifically `p` is not used within the `<asset_name>` tag therefore readability is less of a priority than data size. Unlike `refs` which is defined in the `<asset_name>` tag
- JSON is kept over CBOR or alternatives as this CIP is encapsulated in the 721 metadatum tag and JSON is easier for developers to adopt
### Duplicate data
There could be issues with duplicate payloads. To solve the payload defined in the most recently minted tx takes priority.
## Rationale: how does this CIP achieve its goals?
### Further considerations
- Later we may want to use different reference types, maybe even plutus contract references. Due to this I have defined the `type` tag inside the `refs` (references) tag.
- `p` is used instead of **payload** to reduce bytes. Specifically `p` is not used within the `<asset_name>` tag therefore readability is less of a priority than data size. Unlike `refs` which is defined in the `<asset_name>` tag
- JSON is kept over CBOR or alternatives as this CIP is encapsulated in the 721 metadatum tag and JSON is easier for developers to adopt
### Duplicate data
There could be issues with duplicate payloads. To solve the payload defined in the most recently minted tx takes priority.

Just sketching out a Rationale from the points already included here... maybe also some of what you already wrote above regarding your design decisions.

Especially I think in the Rationale section you should include:

  • why you originally solved this problem with the extra tag, and
  • why you abandoned that idea when CIP88 came along.

Comment on lines +241 to +249
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Finally (last section) include a copyright notice of your choice as defined here: https://github.com/cardano-foundation/CIPs/blob/master/CIP-0001/README.md#licensing

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
There could be issues with duplicate payloads. To solve the payload defined in the most recently minted tx takes priority.
There could be issues with duplicate payloads. To solve the payload defined in the most recently minted tx takes priority.
## Path to Active

As per https://github.com/cardano-foundation/CIPs/blob/master/CIP-0001/README.md#path-to-active. I don't understand the industry well enough to advise on this, but if @Jack-0 you're not sure of acceptance or commercial implementation targets then maybe @Crypto2099 could suggest some.