taproot-assets icon indicating copy to clipboard operation
taproot-assets copied to clipboard

[feature]: Minimal Code Changes for Future Universe Commitment Transaction Support

Open ffranr opened this issue 11 months ago • 5 comments

We need to make minimal changes now to enable seamless support for fully-featured universe commitment transactions in the future. The following steps outline the required adjustments:

  1. Taproot Locking for Minting Change Output
    Modify the minting transaction so that the change output is locked in a way that it can only be spent via tapd. This will involve re-using the existing Pedersen commitment work to commit to the genesis asset ID in the tapscript of the output. The output will use a Taproot format, with the internal key temporarily set to an LND hot wallet key. This setup ensures we can later sign the universe commitment transaction spending this output using an external cold signing key.

  2. User-Enabled Universe Commitment Support
    Add a user-facing option to enable universe commitment during minting. If enabled:

    • Warn the user that the change output will remain unspendable until full universe commitment support is implemented.
    • Restrict the minting batch to include only a single asset group for events with universe commitment enabled.
  3. Metadata Update for Minting Proofs Update the asset minting proof metadata to indicate whether universe commitment is enabled for the minting event.

This change should will allow retroactive application of the feature to past minting events which have uni commitment support enabled.

ffranr avatar Jan 23 '25 16:01 ffranr

This will involve re-using the existing Pedersen commitment work to commit to the genesis asset ID in the tapscript of the output.

Why do we need to commit to the genesis ID here? IIRC, we never finalized the design of what would actually go into this new change output.

The output will use a Taproot format, with the internal key temporarily set to an LND hot wallet key. This setup ensures we can later sign the universe commitment transaction spending this output using an external cold signing key.

These two statements appear to contradict each other.

In an earlier design, the group key was intended to be used for the internal key of this commitment/change output. At that point, we were still tweaking the group key directly with the asset ID, so we would've had to deal with the double tweak issues. With GKR v1, the internal key is "bare", so I think we should be able to just re-use it for the internal key of this Bitcoin commitment anchor output.

One issue with the above idea is that then if the group key is actually a cold key, user interaction may be needed to update the on chain commitment. But perhaps that'll just be a part of the normal minting process?

Warn the user that the change output will remain unspendable until full universe commitment support is implemented.

Seems like something that requires a UI to be truly effective?

Restrict the minting batch to include only a single asset group for events with universe commitment enabled.

So you can't do a re-issue event along with other batch mints? Do we see that as a fundamental limitation, or is this an initial simplification? Seems feasible, along with other re-issuance events that also have a canonical universe comment, with the tradeoff that we'd need multiple of these change outputs?

Roasbeef avatar Jan 23 '25 23:01 Roasbeef

One other thing that comes to mind: do we need a rule that restricts the location of this change address, for the initial mint, and subsequent spends (to refresh the on chain universe commitment)?

Validation can be simplified it clients always know to look at the nth/first output. Here's an example:

  • Minting happens, the commitment output is index 0.
  • That gets spent to update the on-chain commitment with the initial unified commitment tree.
    • There's a change address, as a wallet input was needed to pay for fees.
  • Validators know to watch just the output at index zero for subsequent spends.

Roasbeef avatar Jan 23 '25 23:01 Roasbeef

I think we have a good idea of how we'll aim to update the commitment for issuance, but what about burns and ignored assets?

Burns

The Two Types of Burns

Thinking about it a bit further, there're two classes of burns: first party burns and third party burns. A first party burn is a burn by the issuer (reducing available supply). A third party burn is a provable burn by a user that happens to hold the asset.

First Party Burn Support

For first party burns, the issuer can spend the existing universe commitment output (the latest unspent one), and then update the commitment. With only knowledge of first party burns, users won't arrive at the most accurate supply figure when they "run the numbers". As a result, it is desirable to also support third party burns for the unified commitment.

Third Party Burn Support

One idea to support third party burns is:

  • The sub-system that handle managing the on-chain commitment also watches the issuance tree for said asset.
  • Periodically, the sub-system does a diff of the leaves it knows about, and the leaves that are reported from the Universe API.
  • It'll then take this set of new keys/leave, fetch the burn proof, then start to update its local burn tree (that includes 1st party burns).
  • When the next ticker fires, it spends the on-chain commitment output, to account for this new information.

Ignored Assets

Ignored assets differ from burns and mints, in that they don't have an actual on-chain footprint. Minimally, one can identify an asset on-chain based on a tuple similar to the prevID: (outpoint, asset_id, group_key, script_key, asset_amt). For simplicity, lets assume we're committing this value (alternatively, we can commit the existence proof for the asset in question).

What we need from here is a way to have the group key sign this ignore tuple. One idea is that we re-use the existing virtual tx re-issuance structure. Instead of the virtual output being the newly created asset, we craft something that commits to the asset to be ignored.

Alternatively, we could keep it simple, and just have it be a normal schnorr signature over the tuple. One benefit of re-using the existing group key spending capabilities is that any of the scripts can be satisfied, so it can be a multi-sig script or w/e.

Roasbeef avatar Jan 23 '25 23:01 Roasbeef

This will involve re-using the existing Pedersen commitment work to commit to the genesis asset ID in the tapscript of the output.

Why do we need to commit to the genesis ID here? IIRC, we never finalized the design of what would actually go into this new change output.

By committing to the genesis ID in the output TapScript, we could potentially enable universe commitments for batches involving multiple asset groups in the future. This approach would allow us to include additional outputs, with each output corresponding to a specific asset group.

If an output is tagged with the genesis asset ID in this way, and the commitment output internal key is known to validators, they would be able to identify which output to observe for commitment updates or minting transactions. This would hold true even if, in the future, the batch includes multiple asset groups with universe commitment enabled.

The output will use a Taproot format, with the internal key temporarily set to an LND hot wallet key. This setup ensures we can later sign the universe commitment transaction spending this output using an external cold signing key.

These two statements appear to contradict each other.

In an earlier design, the group key was intended to be used for the internal key of this commitment/change output. At that point, we were still tweaking the group key directly with the asset ID, so we would've had to deal with the double tweak issues. With GKR v1, the internal key is "bare", so I think we should be able to just re-use it for the internal key of this Bitcoin commitment anchor output.

One issue with the above idea is that then if the group key is actually a cold key, user interaction may be needed to update the on chain commitment. But perhaps that'll just be a part of the normal minting process?

I discussed this with Oli, and our idea was to use the LND wallet key as the internal key for now, avoiding the need for an additional round of external key signing. This approach would still leave the option open for supporting external keys in the future.

Warn the user that the change output will remain unspendable until full universe commitment support is implemented.

Seems like something that requires a UI to be truly effective?

Yes, I agree. However, that situation should only be temporary until we can create universe commitment transactions. Ideally, the universe commitment transaction would be broadcast as soon as possible and include change outputs that the user can spend normally.

Restrict the minting batch to include only a single asset group for events with universe commitment enabled.

So you can't do a re-issue event along with other batch mints? Do we see that as a fundamental limitation, or is this an initial simplification? Seems feasible, along with other re-issuance events that also have a canonical universe comment, with the tradeoff that we'd need multiple of these change outputs?

I see this as an initial simplification. In my opinion, we should prioritize supporting asset group minting with universe commitments for a single asset group. This approach is likely to address the majority of the current reissuance minter user demand.

ffranr avatar Jan 27 '25 22:01 ffranr

By committing to the genesis ID in the output TapScript, we could potentially enable universe commitments for batches involving multiple asset groups in the future

But what about the case where we spend several of these change outputs, thereby batching updates to create a new Universe commitment?

I don't think it's defined in any of the other issues yet, so can we lay out clearly here:

  • The structure of taproot output key of the change output (internal key + scripts)
  • The structure of the on-chain universe commitment which spends the change output to serialize updates (internal key + scripts)

If an output is tagged with the genesis asset ID in this way, and the commitment output internal key is known to validators, they would be able to identify which output to observe for commitment updates or minting transactions.

Hmm, I don't think this quite matches my mental model. The output that the validators are watching is the commitment output itself, not this pre-commitment change output. After the first mint, a minting event is what triggers spending that old commitment output, to the new one, which includes all the latest data.

Pertaining to the validators knowing which pre-commitment output to watch: won't that just be included in the issuance proof for the newly created assets? My mental model of the commitment output transactions it that we'd use an ordering rule so validators know which output to watch for a spend (the first one, the second is there is just a change output).

I discussed this with Oli, and our idea was to use the LND wallet key as the internal key for now, avoiding the need for an additional round of external key signing. This approach would still leave the option open for supporting external keys in the future.

Perhaps instead we should build in the concept of a delegated key for commitment updates? This can be specified in the very first issuance proof that creates a new asset group. Using a normal lnd wallet key there is at odds with one of the original requirements that the only ppl that can update the commitment are the ones that can issue new assets.

Roasbeef avatar Jan 28 '25 00:01 Roasbeef

PR https://github.com/lightninglabs/taproot-assets/pull/1325 was merged which completes this issue. Other issues exist to account for the remaining universe commitment work, for example:

https://github.com/lightninglabs/taproot-assets/issues/1451 https://github.com/lightninglabs/taproot-assets/issues/1463

ffranr avatar Apr 14 '25 10:04 ffranr