ord icon indicating copy to clipboard operation
ord copied to clipboard

Collections and Provenance

Open casey opened this issue 2 years ago • 65 comments

See this comment for an update: https://github.com/casey/ord/issues/783#issuecomment-1495169403

Provenance is important for art, and a large part of how it derives its value. We should have some notion of the provenance of an inscription:

  • For an inscription, see who made it
  • For a creator, see which inscriptions they've made
  • Allow referencing an inscription within an artist's body of work by number or name (maybe just name, so they aren't confused with symbols) /ARTIST_SYMBOL/NUMBER

This will likely be accomplished as follows:

  • If the inscription reveal transaction contains more than one input, the first ordinal of the first input is the "prime" ordinal
  • If inscription has a prime ordinal, the first output of the inscription is ignored for the purposes of figuring out which ordinals are inscribed
  • If an inscription has a prime ordinal, the inscription page should link to the prime ordinal's page
  • If an ordinal has been used as a prime ordinal, the ordinal page should list all inscriptions it's made

It should be possible to make a series of related inscriptions:

  • If an inscription is part of a collection, it should link to the collection page
  • The collection page should link to all inscriptions in the collection
  • The collection page should have some description about the collection
  • It should be possible to nest collections. E.g. create a collection that contains multiple collections.
  • Collections should have provenance. You should be able to see the scribe who created a collection, and see the collections issued by a scribe.
  • It should be possible to make a collection closed-ended, e.g. guarantee that it isn't possible to issue more items.
  • It should be possible link to an item in a collection by number or possibly name, e.g. - /COLLECTION_SYMBOL/NUMBER or /COLLECTION_SYMBOL/NAME.

Design sketch:

  • Reuse prime ordinals from #783. A collection is just a prime ordinal, and all the inscriptions that it's made.
  • If you want to add a description to the collection, make an inscription on the prime ordinal used to issue the collection.
  • If you want to close the collection, send the prime ordinal to an OP_RETURN. (I don't actually like this. It seems bad to force burning the prime ordinal of a collection. But, it's very simple.)

casey avatar Nov 15 '22 19:11 casey

this sounds awesome

rot13maxi avatar Jan 31 '23 00:01 rot13maxi

i'm a bit confused by this line

If inscription has a prime ordinal, the first output of the inscription is ignored for the purposes of figuring out which ordinals are inscribed

let me see if i get this right: Say I want to make a collection Astral Babes with good provenance. So I create an inscription w/ info about the collection like normal onto the first satoshi of Outpoint-A, which a value of 10,000 sats

Now say I want to mint the first Astral Babe, the transaction will look like this Inputs:

  • Outpoint-A (10,000 sats)
  • Some other utxo w/ reveal script encoding the first Astral Babe JPG data

Outputs:

  • Outpoint-B (10,000 sats)
  • Outpoint-C (any amount)

Now Astral Babe 1 lives at the first satoshi of Outpoint-C And we can infer that she is part of the Astral Babes Collection, which lives at the first satoshi of Outpoint-B

As I understand, this is a breaking change, because with existing rules, the above transaction would inscribe Astral Babe 1 onto the first sat of Outpoint-B

I'm not sure I like this because it's a breaking change

I will think of something to propose instead

dannydeezy avatar Feb 01 '23 16:02 dannydeezy

This is non-breaking. We'll add a field, destination, which is an integer. destination is an even field, so clients that don't understand it will ignore inscriptions with that field. When an inscription has a destination, it is made on that sat in the output. This can be used to add features which change the existing rules for individual inscriptions.

The destination field can also be used for other features, for example, multiple inscriptions per transaction.

casey avatar Feb 01 '23 16:02 casey

This is non-breaking. We'll add a field, destination, which is an integer. destination is an even field, so clients that don't understand it will ignore inscriptions with that field. When an inscription has a destination, it is made on that sat in the output. This can be used to add features which change the existing rules for individual inscriptions.

The destination field can also be used for other features, for example, multiple inscriptions per transaction.

awesome

dannydeezy avatar Feb 01 '23 16:02 dannydeezy

i wonder if there's a way we can retroactively add items to a collection somehow construct a transaction whos inputs include the ordinal of the collection and the ordinal of the item, as well as an inscription on the collection ordinal that brings the item into the collection

just thinking of ways i can launch my items asap and retroactively add them to a collection

dannydeezy avatar Feb 01 '23 17:02 dannydeezy

Retroactive collections seem doable. This could be a clever solution to #1189: if I buy an inscription, I can add it to my own collection as in set of collected items, by linking it to my collector's (as opposed to creator's) prime ordinal.

corebass avatar Feb 01 '23 18:02 corebass

Until the above can be released, I'm thinking of using Nostr identities for provenance, something like this:

Create a Nostr key that represents the owner of the collection. Create and mint an inscription to announce a collection:

{
"name": "Astral Babes",
"maxSupply": 10000,
"owner": npub12344(nostr-pub of owner)
}

Each time a mint occurs, a separate inscription is also minted that links that item to the collection and adds some metadata:

{
 "inscription_id": "inscription-id-of-the-jpg-inscription",
 "collection_id": "inscription-id-of-the-collection-announcement-inscription",
  "name": "Astral Babe 12",
  "traits": ["hot", "sexy"],
 "signature": "signed-by-the-nostr-key-of-collection-owner"
}

The valid 10,000 items in the collection are the first inscriptions to be mined and also have a valid attestation inscription mined after it.

Furthermore, additional Attestation Inscriptions can be minted afterwards to update the metadata

{
 "inscription_id": "asdfasdfasdfasdfasdf",
  "name": "Astral Babe 2",
  "traits": ["sexy", "hot"],
  "signature": "signed by collection owner"
}

Also can mint a "Freeze Metadata" Attestation which can freeze all future updates to an item or an entire collection

{
 "inscription_id": "asdfasdfasdfasdfasdf",
  "freeze": true,
  "signature": "signed-by-collection-owner"
}

I think the key here is to decouple the inscriptions from identity. Inscriptions are messages, whereas identities are nostr keys

dannydeezy avatar Feb 01 '23 18:02 dannydeezy

A distinction between creator's prime ordinal and collector's prime ordinal would be chronological: the first prime ordinal inscription would be the creator's; the latest, the latest collector's.

corebass avatar Feb 01 '23 18:02 corebass

@dannydeezy

Until the above can be released, I'm thinking of using Nostr identities for provenance, something like this:

It looks like all the actually metadata in this scheme is in inscriptions, and the only nostr-y bit is the pubkey of the creator, is that right?

rot13maxi avatar Feb 01 '23 19:02 rot13maxi

@dannydeezy

Until the above can be released, I'm thinking of using Nostr identities for provenance, something like this:

It looks like all the actually metadata in this scheme is in inscriptions, and the only nostr-y bit is the pubkey of the creator, is that right?

yeah correct

dannydeezy avatar Feb 01 '23 19:02 dannydeezy

could also link items to a collection in batches like this, to reduce dust these can get minted to an OP_RETURN output as there's not need to send them anywhere after being inscribed. (they could even be just published as OP_RETURN data in the first place...)

{
 "collection_id": "inscription-id-of-the-collection-announcement-inscription",
  "items":[{
         "inscription_id": "asdfasfasdf"
         "name": "Astral Babe 1",
         "traits": ["hot"]
      }, {
          "inscription_id": "ccasdfasfasdf"
         "name": "Astral Babe 2",
         "traits": ["sexy"]         
      }, {
         "inscription_id": "ffffaaaasdddsd"
         "name": "Astral Babe 3",
         "traits": ["inquisitive"]
      }
  ],
 "signature": "signed-by-the-nostr-key-of-collection-owner"
}

dannydeezy avatar Feb 01 '23 19:02 dannydeezy

actually yeah, there's no reason collection or metadata announcements need to be inscriptions, because they aren't "owned" or "transferrable", so the initial announcement:

{
"name": "Astral Babes",
"maxSupply": 10000,
"owner": npub12344(nostr-pub of owner)
}

and messages that link items to the collection:

{
 "inscription_id": "inscription-id-of-the-jpg-inscription",
 "collection_id": "inscription-id-of-the-collection-announcement-inscription",
  "name": "Astral Babe 12",
  "traits": ["hot", "sexy"],
 "signature": "signed-by-the-nostr-key-of-collection-owner"
}

could just be encoded as OP_RETURNs...

dannydeezy avatar Feb 01 '23 20:02 dannydeezy

ah but the issue is OP_RETURNs have a byte limit, I see. In that case, perhaps they should be inscriptions

dannydeezy avatar Feb 01 '23 20:02 dannydeezy

Could you open a discussion or something for this? It's totally reasonable to discuss, but I don't want people to think it's recommended/supported/under consideration as the official way of doing this. Just hid the comments, just want to keep this issue focused on the planned implementation for ord.

casey avatar Feb 01 '23 22:02 casey

Could you open a discussion or something for this? It's totally reasonable to discuss, but I don't want people to think it's recommended/supported/under consideration as the official way of doing this. Just hid the comments, just want to keep this issue focused on the planned implementation for ord.

if ord is definitely going to go this route, then I would request that we consider some way in which a bunch of items launched today before this feature is released could have a path to becoming compliant with the standard that does get decided on

dannydeezy avatar Feb 01 '23 23:02 dannydeezy

started discussion here: https://github.com/casey/ord/discussions/1460

rot13maxi avatar Feb 01 '23 23:02 rot13maxi

If you figure out another way to do provenance, e.g. a master inscription with the txids, or nostr, etc, then you can publish that on the project page such that that users can verify it. I can't promise specific support for anything in ord though.

casey avatar Feb 02 '23 00:02 casey

Reuse prime ordinals from https://github.com/casey/ord/issues/783. A collection is just a prime ordinal, and all the inscriptions that it's made.

Is this linking the correct issue? it's just linking back to this one

dannydeezy avatar Feb 02 '23 04:02 dannydeezy

@dannydeezy Yup, that links to this issue.

casey avatar Feb 02 '23 05:02 casey

If i'm understanding correctly, i think there is a challenge with this approach:

Since the "collection prime ordinal" must be explicitly included in every single item inscription transaction, it means that we're gonna start running into too-long-mempool-chain issues. Mempools do not accept a chain of more than ~30 unconfirmed transactions, so that means only 30 items can be minted per block. This hinders the ultimate degen experience of a full 10,000 item collection getting minted out in minutes

dannydeezy avatar Feb 02 '23 10:02 dannydeezy

Curious for thoughts on this - a way to almost do what's mentioned here but without requiring the collection ordinal to be present on every mint transaction: https://github.com/casey/ord/discussions/1469

dannydeezy avatar Feb 02 '23 10:02 dannydeezy

Mempools do not accept a chain of more than ~30 unconfirmed transactions, so that means only 30 items can be minted per block. This hinders the ultimate degen experience of a full 10,000 item collection getting minted out in minutes

Multiple inscriptions per transaction, tracked in #876, fixes this. Can RBF one mint transaction to include more and more inscriptions, until eventually you mine a single four megger that includes all inscriptions and only needs to move the parent ordinal once.

casey avatar Feb 07 '23 23:02 casey

Alternative scheme if BIP-322 can be used for message signing to prove collection, by explicitly signing using the aggregate signatures from all other inscriptions' genesis addresses. This is useful if they don't come from the same prime ordinal, but you want them as a collection post-inscribing because you have the keys to each genesis addresses.

Message to sign by all addresses within the collection:

Data row Type Description
Nonce (uint64) Required Default value of 0 if unused. Nonce can be used by marketplaces or individuals to attest ownership of collection.
Inscriptions ID Required inscription_id of all the inscriptions in the collection, on every subsequent newline. All the genesis addresses listed here must sign this message

rayonx avatar Feb 18 '23 13:02 rayonx

blaeeeeeeeeeghtghghghg:

parent: inscription.parent.and_then(|parent| if inscriptions.contains(parent.txid) { Some(parent) } else { None }),

casey avatar Feb 27 '23 20:02 casey

Provenance is important for art, and is a large part of how it derives value. More broadly, establishing a standard for on-chain provenance using Bitcoin’s proven foundation enables provenance for any sort of digital artifacts.

We should have some notion of provenance for inscriptions that satisfies these requirements:

  1. For an inscription, see who made it
  2. For a creator, see which inscriptions they've made
  3. Allow referencing an inscription within an artist's body of work by number or name /PARENT_INSCRIPTION/NUMBER

This will be accomplished as follows:

  • We are introducing the concept of parent-child relationships between inscriptions
  • When an inscription is created, it can be made the child of an existing inscription, which becomes its parent
  • The UTXO that currently holds the parent inscription is an additional input to the reveal transaction for the child inscription and spent to a separate output in the reveal transaction
  • The parent relationship needs to be established when an inscription is created and cannot be added or changed later
  • An inscription can only have one (or no) parent
  • If an inscription has a parent, the child's inscription page will link to the parent's inscription page in the ordinals explorer
  • If an inscription has been used as a parent inscription, the parent's inscription will contain links to all of its child inscriptions in the ordinals explorer

This concept can be used for provenance (with the parent inscription representing an artist), and it can also be used to establish collections:

  • If an inscription is part of a collection, all inscriptions that are part of the collection should have a single parent inscription representing the collection as their parent.
  • The collection inscription could in turn have the inscription representing the artist as its parent.
  • Additional levels can also easily be established, for example to establish groups of collections, or sets in a collection.
  • Collections can be made closed-ended by burning the collection inscription.

veryordinally avatar Mar 04 '23 01:03 veryordinally

so what prevents someone from creating a collection from a parent inscription they bought/acquired? seems like a great way for scammers to create "official" collections from someone else's inscription

loon3 avatar Mar 04 '23 18:03 loon3

@loon3 I believe this specification is what would prevent your scenario, since the parent-child relationship can be established only at the moment of the inscribing, and cannot be changed afterwards.

The parent relationship needs to be established when an inscription is created and cannot be added or changed later

dsv9 avatar Mar 04 '23 18:03 dsv9

yes for the child, but the parent is simply an inscription you already hold (if i read that right)

loon3 avatar Mar 04 '23 18:03 loon3

Let's determine the problem first, We need to know which inscription belongs to which collection or an artist. There are multiple methods suggested in this thread to make this happen, but there are some problems that occur over and over. Provenance needs to be structured very carefully to avoid problems in the future, that's a big deal. Parent inscription - from what I understand, you can't forecast the inscription id of the child, so the parent must be created after we create the child. That can work but limits functionalities like dynamic allocation of pieces in the collection, and if you want to allow your community to inscribe the NFTs (to avoid paying all the fees), they need to trust you to wrap it all with a "parent inscription" that will state that they are within the collection.

Signatures - The convo here about "where" to place the signature is pretty much irrelevant, as there are multiple ways to add metadata (natively into the files -exif and such, multipart content type, another inscription which indicates). The real focus is on how and what we should sign. a general message from the author's wallet is vulnerable because an attacker can take this signature and attach it to another inscription which will make it "official".

There are two solutions that can work:

  1. Pre-inscribing: Adding metadata of "token_id","collection_name", "author wallet", and "unique_signature" into the inscription. and the unique signature will be based on https://en.bitcoin.it/wiki/Message_signing which can be validated later on, and will contain the "token_id" + "collection_name" + "author wallet". That way the signed message is not general as it is represented by each "token_id" which is unique for every inscription in the collection. This can be generated upfront and added to the file natively before the inscribing even begins. [Big advantage here is that we can leverage the web3.js infra which is widely adopted already to create signatures from other protocols]

  2. Post-Inscribing: Creating a new inscription with the metadata that is meant to be the parent. It will include the data of: "inscription id", "collection_name", "author wallet", and "unique_signature". The unique signature will contain "inscription id"+"collection_name",+"author wallet". That way we can validate that this inscription really belongs to the author or collection we want. (we can also create metadata-inscription (parent) for multiple child inscriptions, with 1 signature that can be more efficient in fees).

In both solutions, we are leveraging the signing functionality to determine the authority of the inscriptions but one is based on "inscription_id" and one is determined by "token_id".

FYI: We have created a tool to add metadata into jpegs https://digital-artifacts.io already which you can test for that purpose. it is currently biased toward solution number 1 (pre-inscribing) but will be changed as to what the project will decide. Screen Shot 2023-03-04 at 21 52 56

WinkyDev avatar Mar 04 '23 19:03 WinkyDev

One tradeoff with the “have the parent be an input to the reveal tx” method of linkage is that collections will have to be inscribed serially (at least in terms of the transaction graph, in practice, CPFP would let you have ~20 of them in the mempool at a time”. Common practice for medium to large collections now is to try to bulk inscribe in parallel. Artifacers will have more complex transaction management for larger collections.

Then again, maybe thats desirable in and of itself. A large collection with common inscription input would itself be a feat until better tooling is developed.

rot13maxi avatar Mar 05 '23 18:03 rot13maxi