formal-ledger-specifications
formal-ledger-specifications copied to clipboard
`scriptsNeeded` check in Dijkstra
I'll leave this here for documentation purposes: We don't want to do an equivalent of scriptsNeeded on subtransactions because it restricts potential optimization use cases. E.g. if we have lots of subtransactions that need the same script, it's better to only include it at the top-level. This would be prevented by checking scriptsNeeded on subtransactions.
As a consequence, checking allowedLanguages at the subtransaction level is a lot more difficult, since we'd have to provide the missing scripts as context. We can't allow older Plutus scripts in subtransactions anyway (since they might rely on transaction balancing as part of their design) so for now it doesn't matter where we check allowedLanguages: if a transaction uses subtransactions, no script can be V3 or earlier. However, in the future it may or may not be useful to restrict languages locally.
This also highlights a potentially important issue for script authors. When writing a V4 script, you can a-priori not rely on transaction balancing for things like optimizations. A script that wants to rely on transaction balancing must first check that it isn't run as part of a subtransaction.
The following thoughts are closely related to the last paragraph:
- currently, the design says that that all inputs of all transactions in a batch have to be in the UTxO set as it is before the batch is applied (*)
- old (V3) style Plutus scripts are not allowed in batches that have more than 1 transaction
- we could relax the constraint (*) by checking the inputs agains the updated UTxO instead because users can account for this relaxation in the way they build V4 scripts
- relaxation would allow batched transactions to spend outputs of preceding transactions in a batch, thus making it possible to chain multiple steps of a script into a batch, using batch observers to make sure that the batch is not separated into pieces
Reasons we currently do not allow this : it creates a lot more potential for bugs in scripts.
A script that wants to rely on transaction balancing must first check that it isn't run as part of a subtransaction.
That is, some scripts will already have to check transaction balancing if they care about it, it may even become standard practice to check some aspects of balancing. This will directly address the issues that come up as a result of allowing chaining of UTxO producing and consuming in a single batch, namely flash loans (this includes flash loans of thread tokens, which may disrupt the correct operations of scripts).
some scripts will already have to check transaction balancing if they care about it
A script that wants to rely on transaction balancing must first check that it isn't run as part of a subtransaction.
To make this check easier, I think we should add a boolean flag into the plutus script context indicating whether it is a sub-transaction or a regular transaction. Note that it would not be exactly equivalent to checking whether sub-transaction balances out or not, since there won't be anything in the rules that will prevent balanced sub-transactions, but I doubt that it will be a common pattern.
Regarding this point:
We don't want to do an equivalent of
scriptsNeededon subtransactions because it restricts potential optimization use cases. E.g. if we have lots of subtransactions that need the same script, it's better to only include it at the top-level. This would be prevented by checkingscriptsNeededon subtransactions.
I feel that it would still make sense to have a check similar to the current scriptsNeeded at the level of subtransactions. In contrast to what is done in Conway, this check would compare the scripts that a subtransaction requires against all scripts referenced/provided within the batch (via reference inputs, transaction inputs or witnesses). Note that although this check would be local to a subtransaction it would rely on global information about the batch.
To make this check easier, I think we should add a boolean flag into the plutus script context indicating whether it is a sub-transaction or a regular transaction.
I think this should be up for the Plutus team to decide. No matter how it's implemented, they probably should provide some API, e.g. a guardTopLevel function that errors out if the script runs at the subtransaction level and continues otherwise. And it's probably best to leave it up to them to decide what's the best way to implement it.
I feel that it would still make sense to have a check similar to the current
scriptsNeededat the level of subtransactions. In contrast to what is done in Conway, this check would compare the scripts that a subtransaction requires against all scripts referenced/provided within the batch (via reference inputs, transaction inputs or witnesses). Note that although this check would be local to a subtransaction it would rely on global information about the batch.
You're right, the question of whether subtransactions need to directly reference their scripts is independent of the question of where we do the scriptsNeeded check (which is an implementation detail). For that, we can either do it at the top-level (which then needs to iterate over all the subtransactions anyway) or at the subtransaction level given a context from the top-level. Phrased like that, it does seem that checking it at the subtransaction level is more natural.
I think this should be up for the Plutus team to decide
Plutus team always asks Ledger what should be in the context, cause it is very much ledger specific and they usually don't care what goes in there. So, it is really up to the ledger team to suggest a solution, but of course Plutus team will have the final say, since context is defined in plutus-ledger-api
I feel that it would still make sense to have a check similar to the current scriptsNeeded at the level of subtransactions.
I totally agree with you as well. scriptsNeeded is checked at the sub-transaction level, while scriptsProvided will be populated by the whole transaction including all sub-transactions. This approach will reduce duplication, while providing decent failures