[NIP] Allow some Output Lock Scripts to Validate
Meta
For context, NIP stands for Nervos Improvement Proposal. This is part of a list of changes that we’d like to see on L1. This stems from our experience on the field, building protocols on top of L1.
Context
Lock Script vs Type Scripts
In the Nervos Network, the distinction between type scripts and lock scripts is fundamental to understanding how transactions are validated:
- Lock Scripts: These are primarily responsible for defining the conditions under which a specific output can be spent. They act as a form of access control, determining who can use the funds associated with a particular output.
- Type Scripts: In contrast, type scripts are more versatile and are executed on outputs. They can contain logic that not only validates transactions but also defines how the output can be used in future transactions.
In summary, lock scripts are about access control, while type scripts enable more complex interactions and state changes.
L2 are Not the Solution
For example, on one side, L1 lacks a Shared-State Execution Layer, so there is no efficient shared-state execution layer on Nervos.
On the other side, while the discussion is still very much open, it seems that generic L2 solutions are currently not viable:
-
Historical Failures: Past L2 initiatives have not achieved sustainable development due to timing issues and insufficient developer interest, leading to skepticism about future L2 efforts.
-
Complex Implementation: Developing a new L2 with shared state is complex and resource-intensive. The effort required may not yield better results than enhancing existing solutions on L1.
-
Ecosystem Readiness: The Nervos ecosystem is not thriving enough to support a generic L2. There is a need for focused solutions that address specific use cases right on L1 rather than a broad, generic approach.
In summary, the combination of these factors makes L2 solutions currently impractical and less appealing compared to enhancing the L1 capabilities.
Proposal: Allow some Output Lock Scripts to Validate
In light of building directly on top of L1 and enhancing its capabilities, I believe that we should talk more openly how to improve the current L1.
I’d like to extend the functionalities of Lock Scripts to closely follow those those of Type Scripts.
Okay, well, traditionally Lock Scripts are primarily responsible for defining who can spend a cell, so the inclusion of a lock exclusively as output currently means:
- The lock will not be needed as CellDep in that tx
- The lock will not be able to validate the output cell
Which brings:
- Output cell lock may be unwittingly invalid, for example in its format.
- Output cell lock may be maliciously invalid, for example forging cells.
The first problem usually is not an issue. Sure, it may irremediably lock up user funds, but usually enough testing before production can iron out these problems.
The second use-case is much deeper and problematic, leading to attacks that are difficult to discover by reviews & audits and even more difficult to prevent.
The current best practice is: use Type Scripts to validate protocol logic.
And that’s sounds okayish until you discover that:
- Type Script of cells are already occupied by UDT Types Script. (While xUDT attempted to allow custom logic execution, it ultimately failed in this regard. Also not all Types are xUDT.)
- A user lock on a cell fully prevent the cell from being unlocked with custom logic.
- A protocol must not be designed against a specific lock, even when this lock would allow a secondary unlock.
- CoBuild may alleviate this problem, but Cobuild may come or not, it is not a given. Also, it may or not fully solve this kind of issues as the advice would still be: design protocols that can work with or without CoBuild.
Which points to: Lock Script must be able to safely validate protocol logic, even when only included as output.
Well, putting religious judgment aside and understood that L2 will not save us all, this is already creating issues for securing L1 protocols and so it must change as soon as possible.
Implementation Ideas
I dream for all output locks on Nervos L1 to be free of their shakles!!
Since that may not be realistic, because old Lock Scripts may throw errors in this new environment, we need to design a way that allow selected Lock Script to execute as output while keeping the compatibility with old locks and changing as little as possible the current infrastructure.
A few ideas that come to mind are:
- Reserve one bit in the type of Script. Now we have
type, data, data1, data2...
. I’d like to proposetype+x, data+x, data1+x, data2+x...
. Ideally over time, most references would migrate to the...+x
variant as it’s just safer. - All new type of Script always execute also when included output lock, so for example all new
data3...
where all cell scripts execute always. Nice, but reference by type are always upgraded to the latest VM version, so this change could cause major breakages unless we also change the behavior of references by type (which we should BTW).
Feedback
Do you have any doubt or question? Please feel free to ask and provide any feedback!!
@janx @xxuejie we already talked about this once, not sure where or when. Which roadblocks do you see in implementing this change of requirements?
Love & Peace, Phroi