Idea discussion: Allow PlutusV1-V3 with Nested Transactions
I had an interesting discussion with @fallen-icarus and I wanted to write up my idea before it fades away from my brain.
We were discussing the desire to use CIP-159 with PlutusV1-V3, which, by itself, could be dangerous, since new features cannot be translated to older scripts and filtering out new fields, like deposits would violate implicit invariant that transaction balances out (eg. there is a deposit of 5ADA into an account, which PlutusV3 script can't see, thus it will look like the whole transaction does not balance out)
At this point I remembered an ability that Nested Transaction will bring to the table, namely PlutusV4 script will happily coexist with PlutusV5 script that uses features that PlutusV4 does not understand, as long as they are in separate sub-transactions. By itself, this capability does not help us with PlutuV1-V3 scripts. However, this got me thinking... What if we allow PlutusV1-V3 scripts in the top level transaction, even with presence of sub-transaction in it, but only when top level transaction itself balances out and passes all of the rules that are today in Conway (I don't mean literally running Conway rules, I mean morally same validation that PlutuV1-V3 scripts would expect in a transaction).
I am not quite sure at this point if there is an easy way to implement this or not, but conceptually this idea should be sound:
- Because top level transaction is processed last, for all intents and purposes it will look like if all sub-transactions were regular transactions processed in a block prior to the top-level transaction because top level transaction would be isolated form them.
- PlutusV1-V3 scripts will be oblivious to the fact that sub-transactions were also processed in the same transactions. The only notable difference will be a higher fee and potentially higher collateral, which is not a forbidden property today.
This would open up a nice opportunity for future compatibility of older scripts to be mixed with new features. In particular for CIP-159, it would be possible to say use PlutusV2 script in a transaction that itself has a sub-transaction that deposits 5ADA into an account with only one restriction that it can't be the top level transaction that produced that ADA, it mwill have to come either form that or another sub-transaction.
So, the caveats to this are, when PlutusV1-V3 script is present at the top level:
- all sub-transactions will have to balance each other out (if there is only one sub-transaction than it itself will have to balance)
- top-level transaction cannot use any of new features. So, it cannot rely on any sub-transaction to provide anything for its validity, no datums, no reference scripts, etc.
If there is a way to enable such use case without a lot of work, I believe it would be worthwhile to implement.
Right after waking up today in the morning, I realized that a very simple implementation is indeed possible for this feature:
Upon validation of the top level transaction, and after processing all sub-transactions, we check whether there are any PlutusV1-V3 scripts in scriptsNeeded and if there are, then we simply validate the top level transactions with subTransactions field reset to empty. However it comes with the caveat that we need to make sure that we do not change the original bytes upon such reset, otherwise all signature checks will fail. We'll also need to check consumed == produced with and without sub-transactions.
I am not sure yet whether this is the best possible solution, but it seems it would take care of all of the necessary restrictions and would be fairly simple to implement.
This sounds reasonable I think (from first glance only)! I will try to think about this more thoroughly later. Seems like this would even still allow (later on) making it possible transactions to spend UTxOs added by other transactions in the same batch.
Actually had some thoughts :
- the second Top-Level-Tx validation is just to re-run the scripts? why do we need to check other things in the tx?
- how do we avoid re-validating the PlutusV4 scripts in the top-level tx?
the second Top-Level-Tx validation is just to re-run the scripts? why do we need to check other things in the tx?
Not exactly, it wouldn't be the second validation of top level (we want to avoid duplicate computation), instead it would be an alternative mode of its validation. If top level has PlutusV1-V3 script then for the top level it would be classic validation as if it doesn't have any subtransactions, except for one check that would ensure that all sub-transactions balance out in isolation from top level transaction.
how do we avoid re-validating the PlutusV4 scripts in the top-level tx?
In either case with or without this feature, plutus scripts will be executed as the last check in the top level transaction UTXOS rule (i.e. phase 2) and only when there are no phase 1 failures. It is an absolute requirement that we do not run any scripts if something in Tx is invalid, which means we'll need to collect all scripts with their context for all sub-transactions and only execute them once we are sure all-subtransaction and top-level transaction are all valid.
@polinavino Please come to the ledger meeting tomorrow if you can so we can all discuss this feature
Perhaps it would be possible to validate all transactions (top- and sub-) in balanced mode? I am picturing like, a tx flag that indicates that a transaction is balanced, and it is ok to validate V1-V3 scripts (using the existing function to determine when those are allowed).