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

Add named properties directly to inscription data #2053

Closed
cognitive-canvas opened this issue Apr 27, 2023 · 15 comments
Closed

Add named properties directly to inscription data #2053

cognitive-canvas opened this issue Apr 27, 2023 · 15 comments

Comments

@cognitive-canvas
Copy link

cognitive-canvas commented Apr 27, 2023

Incorporating named properties can significantly enhance inscriptions, especially with regards to NFT compatibility and other applications involving metadata. Although there have been various attempts to integrate metadata, they often involve a certain degree of complexity and indirection, such as using JSON inscriptions that reference other ordinals. This approach is not only unwieldy but also challenging to maintain.

To streamline this process, I propose adding named properties directly to the inscription data. One way to do it is the following:

OP_5 <KEY_0>
OP_7 <VALUE_0>
OP_5 <KEY_1>
OP_7 <VALUE_1>
...

Adopting this method for inscriptions would transform them into key-value stores, effectively resolving a multitude of issues and ensuring entirely on-chain operations. Additionally, this approach appears to be feasible for implementation in a way that is both forward and backward compatible.

@casey
Copy link
Collaborator

casey commented Aug 31, 2023

Since metadata isn't relevant to the protocol, if we use this approach, we should stuff all metadata in a single tag. See #943 for some discussion.

@casey casey closed this as completed Aug 31, 2023
@casey
Copy link
Collaborator

casey commented Sep 1, 2023

After thinking about metadata a bit, I'm actually warming up to this approach. It's extremely simple, covers the main use case, which seems to be adding simple traits to inscriptions, can be displayed easily, and doesn't require a dependency on a format like JSON or CBOR.

We should use odd tags for the key/value pairs, since metadata can be safely ignored:

OP_5 <KEY_0>
OP_7 <VALUE_0>
OP_5 <KEY_1>
OP_7 <VALUE_1>
...

Keys and values would be UTF-8 encoded text, and would be displayed in a nested <dl> on the inscriptions page:

<dl>
  ...
  <dt>metadata</dt>
  <dd>
    <dl>
      <dt>KEY_0</dt>
      <dd>VALUE_0</dd>
      <dt>KEY_1</dt>
      <dd>VALUE_1</dd>
    </dl>
  <dd>
  ...
</dl>

@casey casey reopened this Sep 1, 2023
@casey
Copy link
Collaborator

casey commented Sep 1, 2023

@veryordinally Actually thinking now that this might be the best approach. What do you think? Also @raphjaph, take a look at this.

@Psifour
Copy link
Contributor

Psifour commented Sep 1, 2023

We are actively using this in our tech demo of quadkey.

While you will 100% not be interested in the product (for obvious reasons), the usage is a really cool example of how these can be used.

Specifically, we use the following envelope:

OP_FALSE
OP_IF
OP_PUSH "ord"
OP_PUSH 1
OP_PUSH image/svg
OP_PUSH "qey"
OP_PUSH {4 byte binary representation of the quadkey}
OP_PUSH 0
OP_PUSH {content blob}
OP_ENDIF

I spend a fair bit of time looking at on-chain transactions and the envelope (as well as indexing non-standard inscriptions) so was very comfortable with the current rule that user-defined/application-specific operations needed to be prefixed with a byte that is odd (to avoid conflicts with protocol reserved even bytes), this led to us using 'qey' (q for quadkey instead of k for key) which begins with an odd byte.

I would love to engage on this topic as I have already been experimenting with this probably more than most other developers in the space (excluding yourself). Interesting envelope mechanics I have explored include (but are not limited to):

  • Injection in 'non-standard' parts of the transaction to include OP_RETURNs and SegWit Witness data. More options would cover more use-cases in ways that make more sense. OP_RETURN inscriptions make a massive amount of sense for the (in my opinion stupid) BRC-20 as they would no longer be bloating the UTXO set with inscriptions they will NEVER move again (due to being below the practical dust limit).
  • Treating the mime type field as optional (most content types can be identified easily with a simple check of the first 20 bytes). This allows saving a fair bit of space for known content types as well as the creation of some really neat polymorphic assets.
  • Adding a 'content-encoding' field (using OP_PUSH 2 in testing environment as this would be an excellent example of a protocol level field). This would be AMAZING as it would facilitate adding gzip/br support while leaving the option open to embrace future accepted web encoding standards. Allow pre-gzipped inscription content #2253

@Psifour
Copy link
Contributor

Psifour commented Sep 1, 2023

We also index this KV store already as it seemed that it's use for application-specific development was always your intent when you reserved the even bytes.

Other examples of it's use include Unisat's previous experiment of storing a 6-byte timestamp with a key of 'unisat' that indicated when they received the request for inscription.

OP_PUSH "unisat"
OP_PUSH {6 byte timestamp}

@casey
Copy link
Collaborator

casey commented Sep 2, 2023

One thing to keep in mind is that my original intent was that both odd-valued and even-valued keys would be reserved for protocol-level data. The difference in handling is because some fields can be ignored when they aren't understood, for example the proposed parent field, and some can't, for example the proposed offset field. If an implementation doesn't understand the parent field, it just won't display the inscription is having a parent, whereas if an implementation doesnt' understand the offset field, it would display the inscription in the wrong location, which is dangerous.

@casey
Copy link
Collaborator

casey commented Sep 2, 2023

Also @cypherpork, you might want to take a look.

@Psifour
Copy link
Contributor

Psifour commented Sep 2, 2023

One thing to keep in mind is that my original intent was that both odd-valued and even-valued keys would be reserved for protocol-level data.

We really should talk more. If this proposal becomes the standard we will 100% index it in addition to the existing data. One of my large goals is to eventually index all non-transaction data about Bitcoin (old OP_RETURNs, counterparty assets, and even oddities like the two cases of identical txid).

@BennyTheDev
Copy link

I would additionally propose a collection identifier field (not all collections are inscribed by the creators). I know that projects could simply use one of the k/v pairs, but having a defined place for that would make it a lot easier to pull rarities and rankings in a standardized way.

@rocktoshi
Copy link

Really liked the notion of a prime sat that could render an inscription immutable by burning it, so that creators could choose mutable or immutable, and collectors could easily understand if an inscription or collection is one or the other.

If must choose only one, immutable best; but I envisage scenarios where altering metadata could be desirable and legitimate.

@stet
Copy link

stet commented Sep 5, 2023

OP_5 <KEY_0>
OP_7 <VALUE_0>
OP_5 <KEY_1>
OP_7 <VALUE_1>
...

This is what I have been doing in my envelope designs as well. I also use a key to signal if extended metadata exists in an OP_RETURN (for out-of-band non-standard metadata w/o expectation of interpretation/presentation beyond app-specific).

Something else I have/had is an inner OP_WRAP to signal the start/end of standard metadata, but I know this is unnecessary extra data. This was used because I was experimenting with some keyless values for other purposes (not metadata). I mention it here only to see if this surfaces any other use cases to consider now that this is metadata standard is a focus.

@Psifour
Copy link
Contributor

Psifour commented Sep 5, 2023

When you all say OP_3 and OP_5, do you actually mean,

OP_PUSH 3
OP_PUSH KEY
OP_PUSH 5
OP_PUSH VALUE

This would indicate a change to existing inscription parsing logic of allowing multiple instances of the same key (3/5) AND makes order of tags meaningful. This seems sub-optimal, but is definitely preferable to storing them as json. Value should be an arbitrary type of data (less than 520 bytes in length). This is to avoid using more bytes than are necessary for other primitives.

@casey
Copy link
Collaborator

casey commented Sep 5, 2023

When you all say OP_3 and OP_5, do you actually mean,

Yup, that's correct, updated the spec.

Value should be an arbitrary type of data (less than 520 bytes in length). This is to avoid using more bytes than are necessary for other primitives.

This is actually an intentional choice. This is intended to support human readable metadata, and without a schema arbitrary binary data can't be displayed to the user.

@huguojunsy
Copy link

We also index this KV store already as it seemed that it's use for application-specific development was always your intent when you reserved the even bytes.

Other examples of it's use include Unisat's previous experiment of storing a 6-byte timestamp with a key of 'unisat' that indicated when they received the request for inscription.

OP_PUSH "unisat"
OP_PUSH {6 byte timestamp}

Unisat did something self-righteous.

@casey
Copy link
Collaborator

casey commented Oct 25, 2023

This has been implemented.

@casey casey closed this as completed Oct 25, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

7 participants