CHIP-0035: DataLayer Delegation Capabilities
Thanks, Yak, for the submission! This CHIP is now a Draft. Feel free to leave your reviews here. For general discussion of this CHIP, please use the #chips channel in our Discord.
I've updated the CHIP's category to Informational and its sub-category to Chialisp Puzzle at @danieljperry's suggestion. Standards Track/Chialisp is meant for changes to chialisp (the language), not for new puzzles.
I have a few questions for y'all
- Have you considered using the reference merkle tree puzzle here for permissioning: https://github.com/Chia-Network/chia-blockchain/blob/main/chia/wallet/puzzles/p2_1_of_n.clsp? This should support as many arbitrary puzzles as needed without requiring a comittment to the specific available roles. It also should save cost at least in the owner spend case because you wouldn't have to reveal all of the permissioning logic for each spend type.
- Could you elaborate on the additional complexities introduced by wallets supporting oracle management/usage? Currently most wallet UXs have certain assumptions such as "only you can spend your coins" & "once a spend is in place, no other spend will compete to spend the coin a different way". Can you explain how wallets should overcome these existing assumptions and what new UX paradigms might be required?
- Is the assertion of the new proposed memo format that datalayer singletons should not be hinting to their own launcher IDs? Currently if you subscribe to the launcher ID of a datalayer singleton, you will not only recieve the launcher spend from a full node but also the spend of all of its descendants because it is hinting to its own launcher ID. Is this functionality you intended to override?
- Does the proposed oracle spend of
(list (list CREATE_COIN [oracle_fee_address] [oracle_fee]) (list CREATE_PUZZLE_ANNOUNCEMENT ‘$’))recreate the singleton as well? As I understood it, it's manually creating a payment coin to the operator of the oracle but it's not doing anything else. - Is there any plan to support non XCH payments to oracle operators? As the current puzzle sits, it seems like you pay the oracle by burning the appropriate amount of XCH kinda like a fee in order for the oracle spend to be valid. Any consideration given to using the offer puzzle paradigm to rely on an announcement of any kind of asset? Also are there any ideas to support multiple way of paying the oracle?
- (very minor but you don't need to use
$announcements. That's an unfortunately very public misunderstanding that adds 12000 cost to every spend.)
Hi Quex, and thank you for the questions (and the fast review)!
Have you considered using the reference merkle tree puzzle here for permissioning: https://github.com/Chia-Network/chia-blockchain/blob/main/chia/wallet/puzzles/p2_1_of_n.clsp? This should support as many arbitrary puzzles as needed without requiring a comittment to the specific available roles. It also should save cost at least in the owner spend case because you wouldn't have to reveal all of the permissioning logic for each spend type.
We've gone with a new puzzle for a few reasons:
- If any admin/writer puzzles are given permission to update the store, owner spends become more of an assurance (uncommon - day-to-day txes would be done by the admin/writer).
- The admin/writer delegated puzzles would need filters that ensure they're not updating the metadata updater hash. They would also need to re-create the coin via a CREATE_COIN, which would prove difficult since p2_1_of_n does not wrap CREATE_COINs and does not provide the MERKLE_ROOT to the child. To ensure the writer does not change MERKLE_ROOT, you'd have to 'rebuild' the current puzzle and assert it via a condition. You'd have to curry the singleton, NFT state, and p2_1_of_n layers, and that is a lot of args to either provide in the solution or curry in: singleton struct, NFT state layer mod hash, current metadata sha256tree, p2_1_of_n mod hash, and current merkle root.
- Assuming the above are implemented: when the admin layer would change the list of delegated puzzle hashes, you'd have to run an additional validator puzzle that ensures the Merkle root still contains the owner's puzzle hash (we don't want admins to 'kick' the true owner out) and that the other puzzles are either an oracle or wrapped in the admin/writer filters. Otherwise, admins could add access to a puzzle that has the same permission as the owner and then fully take over the store in the next spend (which can be bundled in the same tx). I personally think this is a pretty cool program to code for things like vaults, but, in this case, the custom delegation layer removes the need for a lot of code, including this part.
Could you elaborate on the additional complexities introduced by wallets supporting oracle management/usage? Currently most wallet UXs have certain assumptions such as "only you can spend your coins" & "once a spend is in place, no other spend will compete to spend the coin a different way". Can you explain how wallets should overcome these existing assumptions and what new UX paradigms might be
The former assumption is the easiest to overcome, as wallets already detect coin state changes. All wallets can tell you when they receive new coins, and update their state when transactions are confirmed (some coins are spent, some new coins might be created). Moreover, the official protocol supports subscribing to coin state changes (both on-chain and in the mempool).
As for the latter assumption: TibetSwap/warp.green are great examples since both feature singletons that everyone can spend. They work by fetching the latest coin on-chain and then also looking at the mempool - if there is a spend that's already pending, the drivers will build on top of it and then use the RBF mechanism. Wallets can implement a similar mechanism as the data store essentially becomes a 'shared/public singleton.'
Is the assertion of the new proposed memo format that datalayer singletons should not be hinting to their own launcher IDs? Currently if you subscribe to the launcher ID of a datalayer singleton, you will not only recieve the launcher spend from a full node but also the spend of all of its descendants because it is hinting to its own launcher ID. Is this functionality you intended to override?
The assumption was that the spends would be tracked one by one - after a spend is parsed, info about the new coin would be requested. However, I agree that letting the launcher ID be the hint has the potential to significantly speed up syncing - I will make the necessary updates to change the memo format from dg_layer_memos to (list launcher_id . dg_layer_memos) (the reasoning for removing root_hash and inner_puzzle_hash still stands).
Does the proposed oracle spend of (list (list CREATE_COIN [oracle_fee_address] [oracle_fee]) (list CREATE_PUZZLE_ANNOUNCEMENT ‘$’)) recreate the singleton as well? As I understood it, it's manually creating a payment coin to the operator of the oracle but it's not doing anything else.
The oracle is a delegated puzzle, so the delegation layer add the condition that re-creates the coin for each spend.
Is there any plan to support non XCH payments to oracle operators? As the current puzzle sits, it seems like you pay the oracle by burning the appropriate amount of XCH kinda like a fee in order for the oracle spend to be valid. Any consideration given to using the offer puzzle paradigm to rely on an announcement of any kind of asset? Also are there any ideas to support multiple way of paying the oracle?
Creating XCH payments this way is more efficient cost-wise. While non-XCH payments are not included in this CHIP, they're possible (as you noted) by using the offer puzzle. Moreover, the hinting scheme can be extended to add a new type of oracle that handles payments with CATs. I'm not sure what other ways there are to pay the oracle - could you provide an example?
(very minor but you don't need to use $ announcements. That's an unfortunately very public misunderstanding that adds 12000 cost to every spend.)
I chose '$' after reviewing this puzzle specifically, but it's also used in other places (e.g., p2 singleton). I assumed (list CREATE_PUZZLE_ANNOUNCEMENT 0) would take the same amount of space (-> same cost). Could you please provide the more cost-efficient way to create the announcement? Would be happy to update the spec accordingly.
Let me know if any concerns need more clarification, or if there are any more questions :)
Hello everyone,
You'll notice I pushed two small changes to the CHIP:
- The memo format now uses a store's launcher id as the hint. See my earlier answer for the reason this is better - in short, it allows clients to query a bunch of datastore coins instead of getting them one-by-one. This optimization is worth it, even if it adds
32 * 12.000 = 384.000cost to each spend that changes ownership. - A store's metadata may now hold 3 optional fields: label, description, and size. Any combination is valid (e.g., a store owner might provide a label and the store's size, but no description). To best accommodate this and provide the ability to add more fields in the future, optional fields will be stored as
(key . value)inside the metadata.
See the changes in the CHIP document for full info. The reference implementation & tests have also been updated accordingly.
Hey @Yakuhito , I cannot speak to the rest but regarding:
I chose '$' after reviewing this puzzle specifically, but it's also used in other places (e.g., p2 singleton). I assumed (list CREATE_PUZZLE_ANNOUNCEMENT 0) would take the same amount of space (-> same cost). Could you please provide the more cost-efficient way to create the announcement? Would be happy to update the spec accordingly.
You should be able to just use () in place of $ to save that extra byte and reduce the clvm cost :+1:
@Yakuhito I wanted to propose that we change the standard metadata field size to bytes this way its not ambiguous how to update that data.
Hey @Yakuhito , I cannot speak to the rest but regarding:
I chose '$' after reviewing this puzzle specifically, but it's also used in other places (e.g., p2 singleton). I assumed (list CREATE_PUZZLE_ANNOUNCEMENT 0) would take the same amount of space (-> same cost). Could you please provide the more cost-efficient way to create the announcement? Would be happy to update the spec accordingly.
You should be able to just use
()in place of$to save that extra byte and reduce the clvm cost 👍
I asked for clarification because I don't understand why a byte would be saved. () is treated as 0 and still an atom (serialized as 0x80), so the size should be the same. Here's how I tested:
(venv) yakuhito@catstation:~$ run -d '(mod () (list CONDITION "$"))'
ff01ff89434f4e444954494f4eff2480
(venv) yakuhito@catstation:~$ run -d '(mod () (list CONDITION ()))'
ff01ff89434f4e444954494f4eff8080
(venv) yakuhito@catstation:~$ run -d '(mod () (list CONDITION 0))'
ff01ff89434f4e444954494f4eff8080
@Yakuhito I wanted to propose that we change the standard metadata field
sizetobytesthis way its not ambiguous how to update that data.
I've updated the CHIP & reference implementation accordingly.
Drivers are now available in chia-wallet-sdk starting with version 0.13.0. Note that you'll need the chip-0035 feature to use them.
Special thanks to @Rigidity for making it possible :)
This CHIP is now in Review. Please leave your reviews here. If no major changes are required, we will work toward finalizing this CHIP soon.
Yak and Michael presented this CHIP on youtube here: https://www.youtube.com/watch?v=jyg4Ji9LvKI
We'll be moving this CHIP to Last Call soon. Please leave your review here if you have not already done so. Thanks!
This CHIP is now in Last Call. If no further changes are required in the next two weeks, it will be moved to Final.
This CHIP is now Final. No further changes are allowed, other than adding errata. Thanks Yak and Michael!