-
Notifications
You must be signed in to change notification settings - Fork 325
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
CIP-0038? | Arbitrary Script as Native Script spending conditions #309
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead of extending the native (aka. simple) scripts to encode such rules, IMO it should be possible to solve your use case using plutus directly. If not today, then this CIP should be about extending / changing plutus to what you need?
|
||
# Motivation | ||
|
||
Suppose that you are part of a DAO whose funds are managed by a Plutus contract. Your DAO, in order to receive payments, would like receive ADA or tokens to its script address directly. However, this is non-trivial because applications cannot sent to arbitrary Plutus scripts as they do not know how to structure the datum or what other kind of restrictions may exist for this contract. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure that a UTxO with DatumNone
paid to a plutus script is unspendable? I have not tried this yet, but it should be possible if the script does not look for a datum? If not, then this might be the solution you are looking for instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this not be possible today, this would likely need to go into a PlutusV3
, but changing the native scripts syntax is about the same size of change (IIRC there is even SimpleScriptV2
as a language and this would then be SimpleScriptV3
).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you sure that a UTxO with DatumNone paid to a plutus script is unspendable?
This is unfortunately the case. All spending scripts require datum (it is the 2-argument scripts that do not, such as for minting)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@james-iohk is indeed correct. note that you cannot tell if a script hash inside of a transaction output is a native script or a plutus script without having the script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is about the same size of change
I disagree with this because any change to the Plutus context breaks same-transaction composability (i.e. you wouldn't be able to spend a PlutusV2 tx in the same tx as a PlutusV3 tx)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you elaborate on this? By this do you mean that when specifying a reference input, the datum still needs to be provided in the witness field of the tx, even if the input you're pointing to is an online datum?
I think the answer is yes, but let me try to spell it out. An inline datum in a transaction output can only be used for the script (hash) inside the given output. You cannot just use a reference input whose corresponding output has an inline datum, and have that datum be totted around to all the places it is needed (like how reference scripts work).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the answer is yes, but let me try to spell it out. An inline datum in a transaction output can only be used for the script (hash) inside the given output.
I'm also not sure what you mean by this. The PlutusContext contains all the reference inputs of the transaction. These outputs all contain the datum which may be available inlined.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm also not sure what you mean by this. The PlutusContext contains all the reference inputs of the transaction. These outputs all contain the datum which may be available inlined.
Yes, it is true that inline datums attached to reference inputs end up in the script context, but there is a requirement that each datum hash must have its preimage in the transaction witnesses. What I am saying as that reference inputs (which point to inline datums) cannot substitute for this requirement.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Encoding the datum in the address is an interesting idea! That makes addresses a bit longer, but then resolving the ada handle address could encode the target datum.
I am thinking of something like how URLs work. We are quite familiar with the idea of passing additional information in URLs via e.g. query parameters. That gives you the "one link to click" UX but with the ability to include extra payload to be sent. You could imagine an address format like address?datum=<cbor hex>
. Maybe this is bad UX for other reasons, I just wanted to float it as an idea.
There are also cases where people have seen an address in their wallet from interacting with a dApp, and thought they could send more funds to that address to continue to interact with the dApp, resulting in locked funds.
This seems pretty bad. I would think that on the wallet side you want to be pretty careful with letting people send money to script addresses, but I'm not sure what the ideal UX is.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly; some wallets are starting to warn about that, but the main problem is that the wallets can't tell the difference between a native script and a Plutus script without seeing the script bytes somewhere on-chain. It's totally safe to send funds to a multi-sig address without a datum. They both start 0x70. Hence, I think, #310
|
||
Suppose that you are part of a DAO whose funds are managed by a Plutus contract. Your DAO, in order to receive payments, would like receive ADA or tokens to its script address directly. However, this is non-trivial because applications cannot sent to arbitrary Plutus scripts as they do not know how to structure the datum or what other kind of restrictions may exist for this contract. | ||
|
||
To solve this, one way would be to instead have a proxy contract that receives funds and forwards them to your DAO with the proper structure. Native scripts at the moment can play this role by creating a native script multisig where some set of DAO members have their public keys specified in the spending condition of the multisig. However, this approach has the following problems: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe such a proxy contract could be written in Plutus today. For example with plutus-tx syntax:
proxyValidator ::
-- | Proxied script hash
ValidatorHash ->
-- | Datum, to be ignored. We could also define '()' to be the canonical datum for proxy contracts.
BuiltinData ->
-- | Redeemer, also not needed (depending on complexity of proxy conditions).
BuiltinData ->
ScriptContext ->
Bool
proxyValidator target _ _ context =
-- Very basic example of just ensuring all value gets paid to the right target, to be extended.
valueSpent txInfo == valueLockedBy txInfo target
where
ScriptContext{scriptContextTxInfo = txInfo} = context
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Using a Plutus script to solve this problem won't work unless a PlutusV3 is made that accept no-datum inputs as mentioned in the thread above. I also go more into detail about this in a video (I forgot to add it to the original PR description)
Additionally, native scripts also have the benefit that they don't need collateral so they behave slightly differently that script kinds that require a phase-2 validation. Even if we enable datum-less execution of Plutus scripts (which I think we should), this change to native scripts may still be useful to some -- especially if we end up adding other languages in the future that also don't require phase-2 validation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if we enable datum-less execution of Plutus scripts (which I think we should)
I also think we should make this possible!
Even if we do disagree on the amount of work needed to extend simple vs. plutus scripts, it still seems to me that this would be the minimum viable feature the motivation of this CIP requires.
Would datum-less execution of Plutus scripts allow the use cases you have in mind?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If you have datum-less support for Plutus you still would need 2 hops to achieve this kind of proxy contract because you would need a datum-less templated Plutus script where the template hard-codes the datum content into the contract which then is used to forward the datum to the final contract
That is to say, I think datum-less contracts also enable the same proxy infrastructure
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, the basic structure for the "proxy contract" use case is the same. But the plutus script would also allow to encode other things than just an embedded datum, i.e. whatever you intend to be putting in that side-car plutus script referred by RequireScript
.
Are you planning to create a CIP for that or shall I create one?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
feel free to create one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we solve this problem with a convention for an "empty datum"? Perhaps the cbor 80
(an array of size zero)?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm much more in favour of something like this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As another argument in favor of this adding this native script solution as an alternative to any Plutus improvements, this native script version combined with #310 makes it easier for wallets to know it's safe for a user to send to an address. If they are sending to a Plutus script, there is no guarantee the Plutus script is handling the empty datum script so a warning would still have to be shown to the user
CIP-XXXX/README.md
Outdated
|
||
These problems could be solved by adding a many new native script conditions such as enforcing that the transaction that spends it needs to have a certain NFT as part of its inputs or that the transaction contains a specific output. However, there is no guarantee this is flexible enough for all use-cases and these may bring unnecessary feature creep to the native script feature. | ||
|
||
Instead, the most generic solution is to allow a new condition where a native scripts can only be spent if a specific Plutus script is also part of the transaction input. This allows the multisig to simply handle receiving the funds and having all the complex logic (DAO membership checks, output checks, etc.) to be added to the Plutus script. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am worried that this design opens up the door to the "double satisfaction problem". In other words, someone might place a RequireScript scripthash
condition in their native script, expecting the plutus script to execute exactly once, with un-intended consequences if the script runs is used multiple times in the same transaction. Also, does it matter that the new condition has no way of specifying the datum for the script?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm true, it's possible for somebody to write a smart contract such that using it as a native script condition could lead to unintended exploits. You could try and tackle some of the common solutions to double satisfaction (predicate on the datum, NFT to indicate real version, etc.) inside native scripts but this also complicated the native script language. I feel it would be better to tackle and double satisfaction problem by having the native script require the presence of 2 Plutus scripts -- one is the real script you need and the second is just a script that checks for any double satisfaction issues
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I definitely understand why folks would want this feature.
The beauty of the native scripts, as I see it, is their simplicity. Maybe we could have this CIP be dependent of having a good solution to the double satisfaction problem?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What exactly is the "double satisfaction problem"?
@JaredCorduan's question doesn't specify how the unintended consequences can arise (and of what nature?). Aren't Plutus scripts supposed to be pure functions? So what if a Plutus script runs twice or more?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@JaredCorduan Thanks for the link to an excellent explainer of the problem!
I'd say, if the RequireScript
scripts work just like normal Plutus spending validation scripts, then exactly the same solutions apply (as described in the link). For example, the script could make sure the outputs of the spending transaction refer back to the outputs being spent 1:1.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, I just wanted to make sure that we would be consistent with however Plutus solves the problem, and I wanted to point out that the situation is at least slightly more complicated than folks might realize at first glance.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
someone might place a RequireScript scripthash condition in their native script, expecting the plutus script to execute exactly once, with un-intended consequences if the script runs is used multiple times in the same transaction.
The "double satisfaction problem" seems related to the redundant executions of spending scripts (see here). Right now, spending scripts are executed once for every UTxO spent from the script's address and their is no way around this. In my Maybe Datum PR, I try to address this issue by allowing tx-level spending scripts (i.e., spending scripts that are only executed once per tx). With this change, your concern can be addressed by only using RequiredScript scripthash
with tx-level scripts if the "double satisfaction problem" is relevant.
Thanks to the eUTxO model, you can already design validators that check ALL the inputs from the script's address and then check that the tx outputs satisfy the conditions for the leaving balance. So to use your link's example, since B is trying to trick the validator by using one tx for both UTxOs, the validator can see that T1 and T2 are leaving the address in that tx. Therefore, it can easily verify if the proper amount (20 ADA in this case) goes to A's address. I created a DEX proof-of-concept that uses composable atomic swaps which do exactly this (here). The issue with these tx-level validator designs is that, even though they validate based off the tx context as a whole, they are still forced to be executed once per UTxO which makes them inefficient to use due to redundant executions. So while my DEX does not need to be worried about the "double satisfaction problem", it does suffer from the redundant executions. The Maybe Datum PR seeks to address this in plutusV3.
Edit: Fixed saying "20 ADA" is leaving instead of "T1 and T2" in link's example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
So to use your link's example, since B is trying to trick the validator by using one tx for both UTxOs, the validator can see that T1 and T2 are leaving the address in that tx. Therefore, it can easily verify if the proper amount (20 ADA in this case) goes to A's address
yep, absolutely. if you are aware of the problem, you can guard against it. the problem is that if you are not aware of the potential problem, it's an easy trap to fall into. I haven't grokked your Maybe Datum CIP yet, but thanks for the link.
The idea of being able to redeem datum-less UTxOs at script addresses is very desirable. Here's another idea: have you considered "extending" the validation protocol, such that a value of unit is implied from absence of a datum hash? This solution, I believe, is a simple modification, does not necessitate a hard fork, and also doesn't require a proxy script. The downside of this solution that I can think of, is that developers should then be "careful" with their data models to avoid conflicts, as the One possible solution, that can merely reduce the chances of said conflict, is to introduce another datatype similar to |
I believe this solution does require a hard fork. Imagine you have a group of nodes using the current latest version of the node, and another group of nodes using the modification you described. The first group will not allow datum-less Plutus outputs to be spent, but the later will allow it. Hence they disagree about what is and is not a valid block. |
I see, thank you. I believe I had succumbed to wishful thinking (sigh). |
I'd be reluctant to do anything like this that represents the absence of a datum with a value that could also appear as a valid present datum. That is, I'd want to have the script get |
I agree. But just for the sake of argument, shouldn't the contract already handle random unauthorized UTxOs? Would there really be an issue with this conflict? Also, I think |
I don't understand what you're suggesting, could you elaborate? |
I might need further consolidation regarding my grasp of the eUTxO model, but this is my understanding: since anyone can send any UTxO with arbitrary datum to a script address, a Plutus script should already expect random UTxOs. Assuming a validator implicitly injects a pre-defined value in absence of a datum, two things may happen: either the script does not expect the structure, in which case the transaction is likely to fail (depending on the implementation), or it may already expect it. So in the latter case, from the script's perspective, a datum-less UTxO will be equivalent to a UTxO carrying one of the expected "states." If that statement is correct, can we assume that this pre-defined value (implied by lack of datum) is already handled by existing smart contracts? Would that cause any issues, or lead to security flaws? This is just for the sake of argument of course, since this solution is going to lead to a hard fork anyways (thanks to @JaredCorduan), such a hacky approach is unnecessary. @SebastienGllmt seems to be on the right track. |
Anyone can create outputs with any script hash and any datum, correct. They can also omit the datum. But if they do that, it will fail before even running the script. I don't think that scripts will handle "wrong" datums. My expectation is that this will almost certainly just cause most scripts to fail immediately. There is no problem here: the person creating such a weird UTXO has just made a complicated un-spendable output for themselves. |
@SebastienGllmt I really don't get this argument. Even if you know you're sending to a script address with a simple script, that doesn't make it "safe". Unless you can see and analyse the script, then you/your-wallet do not know what it does, or under what conditions someone might get the funds. It's not "safe" to send to a script address without knowing the script. You have literally no idea what it does. Now it's certainly the case that an advantage of the simple script language is that it is so simple that it can be analysed and so in principle wallets could explain to users what the effect is. But once you know the script at the script address, then you know the language, and there was no advantage to encoding the language into the script address itself. |
responded here to avoid duplicating the discussion |
Thanks @SebastienGllmt I think this is a really important discussion to be having. I'm still trying to wrap my head around the scope of the problem we are trying to solve. There are a number of solutions being compared here, but without a good handle on the problem space its hard to compare trade-offs. I think a document with some use cases would be really helpful. Here is a contribution of my favorite use case. As a user of a lite wallet I would like to interact with a DApp without having to trust any centralized services. I am willing to trust the wallet code, but do not want to sign any transactions my wallet has not created. I want to be sure that the address to which I am sending funds is safe to use. Additionally, if the DApp fails to accept my funds for some reason I would like to be able to get them returned to me. It seems like the combination of reference scripts and proxy contracts are a great solution to this use case. By publishing scripts to the blockchain as reference scripts we get a permanent way to refer to and talk about scripts. Whether by social reputation or formal audit I can trust that a published script is the one I want to use. In the case of a DAO or crowdfunding scenario there is the danger that the script condition will never be met and proxy contracts give me a way to get my funds back. Your suggestion to use native scripts extended in this way seems to solve this use case nicely. I think there may be an alternative solution using the existing Plutus machinery. We publish a generic proxy contract as a reference script that takes 2 addresses in the Datum one for the forwarding address and one for the return address. In both cases I think the real problem is that wallets need to know about the "calling conventions" of these proxy scripts. The wallet needs to know how to create the sending transaction as well as the return one. I think we may really need a broader CIP for wallet <-> DApp interaction conventions. Please forgive me if this is already in a CIP or possibly in the wallet specification document, I can't keep all of these things in my head. |
Using a native script as a proxy contract renders the user input (aka the datum) pretty useless. I don't think we should give up so soon on finding a way to build rich interactions between wallets and Dapps. And I think that @asutherlandus is on to something with the new features we've just enabled with the Vasil HF! Consider something like a new convention for "Dapp addresses". It could contain a normal cardano address together with a transaction input. This transaction input would point to a transaction output on chain that contains 1) a reference script and 2) an inline datum. The reference script would correspond to the script in the address (and could be checked by the wallet by checking the hash). The inline datum would provide a schema so that the wallet could get user input. Note that this also solve the problems discussed in #310. |
I don't think anybody is suggesting we give up. We should definitely come up with other CIPs that enable features like this (I like your suggestion!). However, any other approach is purely complementary to the feature in this CIP. Nothing stops us from implement this CIP which is a fairly easy-to-understand & easy-to-implement feature while also working on other complementary options like the one you described which are more involved |
This proposal makes it easier to pay to a script address by making it so you don't need to pay to the script address, you instead pay to the native script address. However:
I think the alternative that I'm most keen on right now is the one that I sketched in an earlier comment: #309 (comment) Briefly:
The reason I like this is that:
i.e. it's both easier to implement and more general. |
I discovered https://cips.cardano.org/cips/cip13/, so a simpler proposal would be:
|
In the meantime since this proposal's last revision, another author & I came up with some good reasons for replacing CIP-0013 with a more generalised URI scheme... and then some slightly better reasons for not doing it: https://forum.cardano.org/t/cip-generalized-cardano-urls/57464 TL;DR since there were so few uses for URIs (only payment & stake pool links), and (as today) still so little support in wallets, the URL scheme never evolved any further... so much I didn't recall until your last comment that it only covered ada payments as supported by Yoroi in the early days. Maybe a more diverse syntax for Payment URIs would weigh back in favour of a generalised URI scheme after all... but maybe not if it's just adding a single |
CIP-XXXX/README.md
Outdated
|
||
These problems could be solved by adding a many new native script conditions such as enforcing that the transaction that spends it needs to have a certain NFT as part of its inputs or that the transaction contains a specific output. However, there is no guarantee this is flexible enough for all use-cases and these may bring unnecessary feature creep to the native script feature. | ||
|
||
Instead, the most generic solution is to allow a new condition where a native scripts can only be spent if a specific Plutus script is also part of the transaction input. This allows the multisig to simply handle receiving the funds and having all the complex logic (DAO membership checks, output checks, etc.) to be added to the Plutus script. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Instead, the most generic solution is to allow a new condition where a native scripts can only be spent if a specific Plutus script is also part of the transaction input.
I think I may have misunderstood this condition. In fact, I don't know what it means at all. Perhaps you could add as part of the specification an explanation of how the new script clause is actually validated (which you don't say anywhere!).
My original reading was that this meant that there must be some other input which is locked with the given script, but it could also be read as saying that the given script must be run as if it was the validator script for the current input and pass in that case. These are quite different.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
here must be some other input which is locked with the given script
This was the meaning I intended
] | ||
} | ||
``` | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It wouldn't hurt to add a section on how exactly the referred scripts are going to be interpreted. Here's what I would add.
## Script Execution | |
The proposed spending condition of `"type": "script"` may refer to any simple or Plutus script via the `scriptHash` field. The actual script is presented by the spending transaction: either in the witness set or in a reference input. | |
Depending on the type of the referred script, additional processing is done. | |
- native (a.k.a. simple) scripts are recursively evaluated as described in https://github.com/input-output-hk/cardano-node/blob/master/doc/reference/simple-scripts.md, with the addition of the `RequireScript` constructor proposed here. | |
- Plutus scripts are executed as regular spending script as (informally) described in https://github.com/input-output-hk/cardano-node/blob/master/doc/reference/plutus/plutus-spending-script-example.md. This means, the output's datum is passed to the script, as well as the redeemer presented by the spending transaction, and script context (constructed according to the Plutus version) is passed as the third argument. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
additional processing is done
I'm not sure what you mean by this. No additional processing is done, since the script referenced in RequireScript
must be present in some other input and that input is the one who is doing the processing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps, it is bad wording. Would it be clearer if we remove the phrase additional processing is done.
and keep the rest?
For Milkomeda, we're also interested in using this exact functionality for handling of some UTXO entries Users, to use Milkomeda, may want to send their funds to a native scripts. We can make these native scripts only spendable if a specific Plutus input also exists. This Plutus script does nothing but check if the transaction contains a specific NFT in its input set. This means our transactions only need to process 1 Plutus script, and all other UTXO entries are just simple native script spends This allows all Milkomeda funds to be managed by simple native scripts, and allows us to upgrade the control mechanism of the permission NFT without ever having to "upgrade" any Milkomeda UTXO entry (which isn't easily doable since Milkomeda has a lot of UTXO entries and upgrading them all costs a non-trivial amount of ADA in fees) unless it's to upgrade Plutus versions |
I like this. Much better with added motivations. |
```BNF | ||
<native_script> ::= | ||
<RequireSignature> <vkeyhash> | ||
| <RequireScript> <scripthash> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary of a conversation with Las on this:
Although require script is sufficient to do everything one would need, it's kind of tedious because there is no way to specify a datum or a tag (script, mint) in the native script, so it means you need to inline checks in the Plutus script. We could extend this CIP to enable adding other restrictions to the script (ex: passed with a given datum or tag) if that's acceptable to people
If we do this, we also have to consider how to handle inline datums and reference scripts as well
"scripts": [{ | ||
// in the general case, the user such signs like normal | ||
"type": "sig", | ||
"keyHash": "ed6f3e2144d70e839d8701f23ebcca229bcfde8e1d6b7838bda11ac8" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One of the problems is that this only gives you limited account abstraction. What if instead of ed25519, you want some other cryptographic scheme for the multisig? Currently, the only way to access secp256k1 is through Plutus, and if we ever try and move to post-quantum crypto (#441), these would end up all being Plutus
To properly support these, we would probably need a separate CIP to extend native script keyHash
to support different crypto schemes instead of only exposing them in Plutus
also re: "Account Abstraction" I wanted to highlight this video as useful for community review & for us to keep an eye on the relevance of this proposal 🧐 https://www.youtube.com/watch?v=d5ei9vkU15o |
I would love to see this implemented, It would allow for a host of "Exotic Wallets". |
I have a potential use case for this in mind but I have some considerations about this CIP. A note before getting to the considerations: in order to use beacon tokens properly with distributed dApps, all users must use the same spending script. This single spending script must capture the full functionality of the dApp. I am mentioning this requirement because this is influencing my perspective. For context, imagine if you have a script with redeemers A, B, and C. Each redeemer will result in some complicated action taking place. Currently (for my use cases), since all three functions must fit into a single 16 kb script, compromises need to be made about what can go into the script for each function. Using the functionality described in this CIP, it would be possible to break up the aforementioned script into three separate scripts, one dedicated to each function. While before, 16 kb may not have been enough to fit all the functionality for all three functions, by breaking them up into separate scripts, 16 kb would be plenty for a each individual function. The native script itself would then tie the three scripts together by checking that one of the "sub-scripts" was executed in the transaction. This approach would allow all dApps to be modular in design and allow for more efficient executions since "unused logic" is never part of executions. Consideration 1 - At least n but no more than m of kIn the scenario described above, each "sub-script" is dedicated to a given redeemer. It most cases, it would not make sense to allow multiple of the sub-scripts to execute in a given transaction. In the use case I have in mind, this can result in unexpected behavior. Therefore, it would be ideal if the sub-scripts could be forced to execute one at a time. Currently, this must go into the logic of each plutus script to check that they are not being "composed" improperly. Since this CIP is looking to change native scripts already, perhaps it can also add a feature to do this. The multisig is "true as long as n >= threshold". Here I am suggesting making an option for the inverse: "true as long as n <= threshold" but with the requirement that at least one of the scripts is still executed. To make this general in case certain applications do allow for multiple scripts to be executed in a given transaction, I think there should be an option for RequireAtLeastNButNoMoreThanMOfK (feel free to choose a different name). Consideration 2 - How to execute the arbitrary scriptCurrently, executing a plutus script requires one of the following:
In the above example, none of the above are relevant. Using any of the three has drawbacks:
Technically, the staking script option is "good enough" for the example I described above since withdrawing 0 ADA is always possible. However, it is not ideal. The ideal scenario is to have a fourth option for an auxiliary script that can possibly take a redeemer (some use cases might require the redeemer). While there is an option for an auxiliary script with To be clear, the above considerations are not necessary. However, IMO they would dramatically improve the usability of native scripts in contexts like those I described above. Thoughts? |
@fallen-icarus perhaps instead of RequireAtLeastNButNoMoreThanMOfK, it would be enough to just have RequireNoMoreThanMOf, which can then used in combination with the existing RequireMOf to create ranges for validity. This would be simpler and more modular than RequireAtLeastNButNoMoreThanMOfK. For example, to specify that exactly two of four potential plutus scripts are used, the native script can look something like: {
"type": "all",
"scripts":
[
{
"type": "atLeast",
"required": 2,
"scripts":
[
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_1>"
},
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_2>"
},
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_3>"
},
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_4>"
}
]
},
{
"type": "noMore",
"required": 2,
"scripts":
[
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_1>"
},
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_2>"
},
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_3>"
},
{
"type": "script",
"scriptHash": "<SCRIPT_HASH_4>"
}
]
}
]
} Where |
Actually, for even greater simplicity and modularity, maybe we can just add a "None" type (boolean inversion) to native scripts? So, BNF description of native scripts would look like:
Prior to CIP38, there'd be no use for it, but now it may be extremely useful. It would allow for fine-grained control over what redeemers/contracts can or cannot be used in combination with each other. |
My one concern is that smart contracts must always be able to tell the difference between a wallet and another smart contract. This is to prevent voting fraud. I am sure Sebastien has already considered this or perhaps this is a non-issue for reasons I do not understand. In any case, we should be able to accomplish timed recovery for lost seed phrases by using smart contracts as wallets as opposed to blurring the distinction between the two. That said, there seem to be many good reasons for account abstraction. |
@johnshearing this proposal doesn't affect this since it doesn't get rid of end-user wallets in any way. If you're talking about account abstraction more in general (as in a world where we move everything to contracts only and not what this CIP specifically is about), you could consider user accounts as native script with a single key in it or some other way to try and different scripts for users compared to entities, but keep in mind differentiating the two is never fully possible (since you could even have a non-contract wallet that is actually generated using an offchain MPC or something similar) |
Thanks @SebastienGllmt, I think I hear you saying that already it is possible obscure the distinction between wallet and smart contract because you can imagine a way to generate a wallet using multi-party computation. So even if it does matter, it's a moot point with regard to CIP-0038 Now that I think about it, DReps will likely be able to determine which wallets are delegating and when so perhaps no smart contracts would even be needed to setup a voting delegation market. Thanks for helping me work through this. |
Hello everyone, I would like to express my support for this proposal. I have two projects (https://encoins.io and https://wrapper.zkfold.io) that both utilize the paradigm where all Tx validation happens in one script, but the Tx may be spending many UTxOs locked by a (currently Plutus) script that implements the "Require Script" logic. Spending 100-150 script UTxOs that just "Require Script" costs a significant percentage of the total ExUnits budget, especially in terms of memory. While I do not claim that we currently have the most efficient implementation (there is definitely some room for improvement), I do believe the numbers below represent the situation well enough. Here is an example of a transaction that uses the "Require Script" validator: I believe the efficiency considerations alone justify having the proposed upgrade. An alternative, "Tx-level scripts", was discussed here. However, the implementation suggested there is much more complicated, from the perspective of a DApp developer at least. Please let us know if we can help somehow in finalizing this proposal. Thanks! |
I would like to reiterate my support for this proposal, I am in the final stages of deploying a new product for Broclan.io . Having to use Plutus validators directly has a significant impact on efficiency and a very large impact on UX. Implementing my solutions using this script will make everything much more easy so use and safe for the end user. |
@SebastienGllmt we have a new proposal ... which Plutus reps are enthusiastic about implementing (#749 (review)) so please let us know how you feel about the different approaches, and whether you think your proposal here could or should be deprecated. |
@SebastienGllmt given #309 (comment) it seems this approach has been deprecated but please reopen this if you would like to make a case otherwise. @leo42 since you were the last person to confirm support for this proposal, please post here and consider reopening this if you think what was originally proposed here is a better solution than the currently favoured #749. |
Native scripts are often easier to work with as any application that allows users to enter an ADA address to receive funds supports native scripts (the same is not true for Plutus scripts as the app would need to know how to structure the datum). However, limited composability between native scripts and Plutus scripts limits leveraging this fact.
This CIP introduces a way to use native scripts as a starting point for more complex interactions which helps unlock use cases such as simple proxy contracts.
You can learn more about one of the motivations here: https://www.youtube.com/watch?v=5cI1DfrlO0E
see rendered Markdown