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

Collections and Provenance #783

Closed
casey opened this issue Nov 15, 2022 · 67 comments
Closed

Collections and Provenance #783

casey opened this issue Nov 15, 2022 · 67 comments

Comments

@casey
Copy link
Collaborator

casey commented Nov 15, 2022

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 Collections and Provenance #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 casey added this to the Production Inscriptions milestone Nov 15, 2022
@casey casey mentioned this issue Nov 15, 2022
@casey casey modified the milestones: Mainnet Inscriptions, Later Dec 14, 2022
@casey casey modified the milestones: Later, Mainnet Dec 23, 2022
@casey casey mentioned this issue Jan 16, 2023
@casey casey changed the title Creator provinence Provenance Jan 16, 2023
@casey casey changed the title Provenance Collections and Provenance Jan 18, 2023
@casey casey modified the milestone: Beta Jan 19, 2023
@rot13maxi
Copy link
Contributor

this sounds awesome

@dannydeezy
Copy link

dannydeezy commented Feb 1, 2023

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

@casey
Copy link
Collaborator Author

casey commented Feb 1, 2023

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.

@dannydeezy
Copy link

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
Copy link

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

@corebass
Copy link

corebass commented Feb 1, 2023

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.

@dannydeezy

This comment was marked as off-topic.

@corebass
Copy link

corebass commented Feb 1, 2023

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.

@rot13maxi

This comment was marked as off-topic.

@dannydeezy

This comment was marked as off-topic.

@dannydeezy

This comment was marked as off-topic.

@dannydeezy

This comment was marked as off-topic.

@dannydeezy

This comment was marked as off-topic.

@casey
Copy link
Collaborator Author

casey commented Feb 1, 2023

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.

@dannydeezy
Copy link

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

@veryordinally
Copy link
Collaborator

Continuing work in #1963

@clean-casey
Copy link

I am trying to understand the improved security of this approach. My use case is to publish a document and mint a collection of child inscriptions that all reference this document. Can someone describe the benefits of this provenance parent/child feature versus just referencing the parent inscription in the child inscriptions. Thanks

@tyjvazum
Copy link

I am trying to understand the improved security of this approach. My use case is to publish a document and mint a collection of child inscriptions that all reference this document. Can someone describe the benefits of this provenance parent/child feature versus just referencing the parent inscription in the child inscriptions. Thanks

To reference a parent inscription in a child inscription there needs to be a standardized way of validating the relationship, otherwise anyone could make child inscriptions for any parent inscription.

This can be achieved in various ways, but the direction of https://github.com/casey/ord/pull/1963 is to try to do it by moving the parent inscription around as child inscriptions are created.

As others have pointed out in this issue, that will result in a larger transaction size and higher transaction fees than inherently required.

It also still has a relationship validation problem, as @casey described in issue https://github.com/casey/ord/issues/884 and others have raised concern about in this issue. With the current proposal, anyone would be able to make child inscriptions for any inscription they happen to own, even inscriptions transferred prior to the introduction of the feature. That would obviously be very undesirable for many artists and use cases, so hopefully it will be managed in some way before the feature is released. Perhaps a project collaborator can comment on it to provide some clarification.

@clean-casey
Copy link

Thank you @tyjvazum for the additional context. This is very helpful. I am happy to help if I can. Thank you @casey

@rot13maxi
Copy link
Contributor

I think this approach is problematic for collections over a handful in size. The current state of the art is to inscribe a collection in parallel. Requiring a “collection parent” sat to be shuffled into the reveal tx of each item in the collection greatly limits your options for inscribing a collection: you can either do them all sequentially or if you’re very clever with CPFPing the parent around, you might be able to have small batches of 25 in the mempool at a time. The latter approach hasnt been developed (afaik) and may carry some risks and will come with high fees to keep all of those linked transactions in the same block — because you have to cpfp the parent ordinal around, all the the reveal transactions are going to be linked together onchain and move around the mempool as a batch with all of their transaction fees averaged together.

I know people are excited for something to let them do collections in a standardized way, but I dont think everyone understands the current proposal and the implications it will have on the ability to actually inscribe collections.

The inscription envelope has room for headers. I think a more scalable approach would be something like an ord header that references a “parent” inscription and contains a signature (bip322 or otherwise) that proves possession of the parent inscription at the time the child was inscribed. That kind of approach fits better with the current economic and operational needs of artifacers working today.

@bodily11
Copy link

I agree with @rot13maxi. We're looking to inscribe 10k generative collections using better collection standards and provenance information, but requiring a parent inscription in this fashion is unworkable for us. I would definitely prefer some kind of bip322 parent inscription owner signature standard.

@satoshi0770
Copy link

I understand the time limitations of 10k collections.
They can be done in batches of 25 with cpfp, using a large "effective" fee with the 25th.
I also understand the limitations of higher tx fee due to an extra input/output.

But there is something magical when a child inscription has its parent ordinal in its creation (reveal) transaction.

The way I see it, child/parent inscriptions have a higher barrier. But rightfully so because they are more luxurious.

The higher cost, and the need to craft proper cpfp batches. Would drive the market to create quality.

Understanding the market currently wants a standard for 10k pfp eth style collections.
But btc inscription collections can be a different field entirely.
One that is more expensive, but very elegantly includes the parent at the birth of every child.

(A 10k eth pfp collection can still be done, it would just take more time and more fees. I would argue rightfully so)

@rot13maxi
Copy link
Contributor

When I wrote my earlier comment I mentioned the 25-transaction package limit. I had completely forgotten that there is also a policy limit of 101KvB on the whole package. that means that if you wanted to inscribe 25 inscriptions in a batch that had a common parent (that are all part of the same collection), then each one would be limited to less than 4kb. Those are really small. According to one study the average image inscription is 21kb. If you take that as the norm (I would have guessed 50kb), then you can do at most 4 inscriptions per batch to have them be part of a collection. For a medium-sized collection of 1000 inscriptions, that means you'd have to do 250 batches. And you can't put a new batch in the mempool until the old batch is actually confirmed. So you need to submit a batch to the mempool, and get it to confirm, then submit the next batch, and do that 250 times for a 1000 image collection. For larger images (or video or audio or large SVGs or javascript) it will be more batches For a 10k collection (which I would consider to be VERY large), it would take 2500 batches.

Even a 100 item collection is still going to take 25 blocks (with package broadcast after each confirmation) to make this work.

I think we can accomplish all of the things we want to do WRT collections (verifiable onchain (i.e. not in an external DB or with a pointer to an off-chain manifest), allows for provenance and attribution, allows for open/closed sets, etc) with ord envelope metadata without running into relay policy limits that exclude common (and reasonable) usecases.

@rot13maxi
Copy link
Contributor

rot13maxi commented Mar 31, 2023

Alternative ideas that could be formalized a little more and help with the scalability issue (borrowing some ideas from the Taproot Wizards project):

  • inscriptions with a address/scriptpubkey as a common ancestor are part of a collection. Maybe there's a special inscription that can be made using that SPK to set collection metadata (edit: here's an example, if you look at this reveal transaction and follow its inputs, you will see it had this address as it's "great grandparent". The taproot wizards project did the "fan out and inscribe" method that a lot of projects use to inscribe a collection in parallel and not run into package relay limits, but they did it from a common ancestor) If we wanted to standardize on something like "indexers look up to 3 hops back for an address that holds a collection marker sat" or something, then we can accommodate both bulk-inscribed collections and individually-inscribed collections.
  • inscriptions all sent to the same address/scriptpubkey (using the --destination flag on ord wallet inscribe) are part of the same collection. Again, maybe there's a special "marker" inscription that could be made to set inscription metadata.

@timechainz
Copy link

I agree with @satoshi0770 about the glorious opulence of the prime ordinal technique.

I'd like to throw an additional idea out there that could address the scaling issues @rot13maxi raises.

An inscription's reveal transaction may include additional outputs. The first sat in each output may be used to inscribe a child. Using this technique an inscription would be made with a pre-determined number of potential children.

Outputs

0: 10,000 sats - collection anchor
1: 330 sats - potential child 1
2: 330 sats - potential child 2

Advantages to this system are that the number of potential children are known up front and it scales very well. One could immediately send all children to the mempool after confirmation of the parent. Downside is that the index would probably have to track the potential child satpoints.

@casey
Copy link
Collaborator Author

casey commented Apr 4, 2023

Sorry for the delay in getting this feature done! ord is an open source project developed by volunteers, as well as a limited number of paid contributors. Like many open source projects, we have limited bandwidth, and often are dealing with many concerns at the same time. Collections is an important feature, but there are other important things to be done, including fixing bugs and improving the UX of existing features.

Collections is also complicated, and will require careful review and revision. I'm personally optimistic about the state of the design of collections and its implementation. However, it would not be personally acceptable to me to release a feature that was buggy, half-baked, or insecure. As they say: Collections will be done when it's ready, and not a moment sooner.

Enjoy the current features of ord! Development continues :)

ericatallah referenced this issue in metagood/ord Apr 5, 2023
Why:
- Some generative art collections have inscribed all art within a single
parent inscription to save considerable storage space on the
blockchain.
- The ord explorer is unable to currently support collections inscribed
  in this manner.  This commit adds this support.

What:
- In order to support these generative art collections, we need to be able
  to inscribe the metadata for children in an agreed upon JSON spec.
- These child inscriptions are JSON documents containing url parameters
  that instruct the parent inscription to
  render a specific item in the collection.

How:
- Since all art is contained in the parent, we added a simple redirect to
  render the parent inscription with included url parameters.
- There are 3 constraints which must be in the child inscription before
  the redirect can happen:
1. The child inscription must have a parent inscription.
2. The child inscription's body data must be valid JSON.
3. The child inscription's body JSON data must contain a field named
   "is_ord_pointer", with any value.

Proposed JSON standard:
```
{
   "is_pointer": 1,
   "url_params": ["tokenID=4969"],
}
```

Related Issue:
- https://github.com/casey/ord/issues/783

Co-authored-by: Clarke Plumo <clarke.plumo@gmail.com>
@sherbakovdev
Copy link

Here is the proposal for the collection protocol. I wasn't aware of the discussion here, so we have found another solution to this problem with my team: https://brc721.com

@p0stcapone
Copy link

I think this approach is problematic for collections over a handful in size. The current state of the art is to inscribe a collection in parallel. Requiring a “collection parent” sat to be shuffled into the reveal tx of each item in the collection greatly limits your options for inscribing a collection: you can either do them all sequentially or if you’re very clever with CPFPing the parent around, you might be able to have small batches of 25 in the mempool at a time. The latter approach hasnt been developed (afaik) and may carry some risks and will come with high fees to keep all of those linked transactions in the same block — because you have to cpfp the parent ordinal around, all the the reveal transactions are going to be linked together onchain and move around the mempool as a batch with all of their transaction fees averaged together.

I know people are excited for something to let them do collections in a standardized way, but I dont think everyone understands the current proposal and the implications it will have on the ability to actually inscribe collections.

The inscription envelope has room for headers. I think a more scalable approach would be something like an ord header that references a “parent” inscription and contains a signature (bip322 or otherwise) that proves possession of the parent inscription at the time the child was inscribed. That kind of approach fits better with the current economic and operational needs of artifacers working today.

I think that we're over complicating provenance in a number of ways.

Provenance was possible with the first release of ord which supported mainnet: A single UTXO funds many UTXOs which immediately become inscriptions.

For many collections, if you look at the second ancestor of the genesis transaction, you will find one transaction which creates many ouptuts (because this was the simplest and most direct way to set up the funding for each individual inscription). This transaction represents a strong (although slightly imperfect) record of provenance. If this transaction were to create many UTXOs which went to the same address, it would be a perfect record of provenance.

If the initial funding UTXO contained an inscription (perhaps by mandate located at sat Index 0), then it would be very clear that this was the "parent" inscription.

There would be no changes necessary to ord to accomplish this, and there would be many collections who would be adopted by default into the provenance standard if this were adopted.

@rot13maxi
Copy link
Contributor

I like this approach of having common ancestor ScriptPubKeys (some links to examples provided in this comment: https://github.com/casey/ord/issues/783#issuecomment-1492070385)

I think most of the work would be on indexing to add links between related items. On the inscribing side, it can either be handled with external tooling, or if we wanted to have wallet inscribe be able to either do bulk inscriptions or just to add an inscription to an existing collection, it would involve shuffling around some sats to the parent address and then inscribing.

@timechainz
Copy link

timechainz commented Apr 10, 2023

There would be no changes necessary to ord to accomplish this, and there would be many collections who would be adopted by default into the provenance standard if this were adopted.

@p0stcapone In general I like the approach of having a common ancestor define a collection, but would adjust slightly to make fewer assumptions about how collections are inscribed and funded. A few things I would clarify:

  • "A single UTXO funds many..." - There should be a single tx, not necessarily a single utxo. This is especially true if the genesis tx were to include a parent inscription.
  • The language is focused on the "funding" but it should be on the satpoint that is ultimately inscribed. If other utxos are used for fees or padding during inscription it's irrelevant. There are situations such as inscribing on special sats where it may not make sense to graft in the funding sats into the genesis tx. I think this is effectively what you meant anyway.
  • "...create many UTXOs which went to the same address..." - The intermediate address that holds the utxos that will be inscribed on is not really important and some wallets won't even allow sending multiple utxos to the same address (e.g. bitcoin-cli). @rot13maxi 's 2nd alternative "inscriptions all sent to the same address/scriptpubkey" seems like a better way to enforce this.

My $.02

@veryordinally
Copy link
Collaborator

Next step is implementing #2045

@casey
Copy link
Collaborator Author

casey commented Jul 16, 2023

I opened a draft PR with a spec. Comments welcome!

Please note that this spec does not include:

  1. Batching, which would allow making multiple inscriptions in a single transaction.
  2. A tag which makes an inscription not land on the first sat of the first output.

Which makes provenance more useful.

These can be specced and implemented separately, so they aren't included in the initial spec.

@raphjaph raphjaph added this to Tracker Sep 5, 2023
@raphjaph raphjaph moved this to Backlog in Tracker Sep 5, 2023
@casey
Copy link
Collaborator Author

casey commented Oct 24, 2023

This is finally done!

@casey casey closed this as completed Oct 24, 2023
@github-project-automation github-project-automation bot moved this from Backlog to Done in Tracker Oct 24, 2023
@casey casey removed this from Tracker Nov 30, 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