Replies: 3 comments 3 replies
-
|
This sounds great; and would help a bunch in the node. Question: does a tx fail if its trying to insert new code that already exists? Or does this become a no-op? |
Beta Was this translation helpful? Give feedback.
-
I was thinking it would be a no-op. |
Beta Was this translation helpful? Give feedback.
-
Code commitments & completenessTo take a concrete example, a P2ID note code commitment would be specified by:
In a fresh network, when the first P2ID note is created, the transaction kernel:
One attack scenario is:
The situation is now: The I think potential work arounds are:
But I think we're trying to work around the fundamental problem/feature of MAST that an external node referencing X has the same commitment as X itself, and it seems like we may have to go deeper to solve this. Code sizeI think computing the code size is related to the way we commit to code. The commitment methodology should allow the kernel to compute the size without the user being able to cheat by replacing a part of a MAST with an external node. I think the proposed methodology should set us up for computing the size of the underlying MAST, but afaict it does require us to implement MAST hashing, i.e. what I think we wouldn't need this in a centralized setting. For now, the kernel could assume that the data is valid, take a size hint, ... The "Rust protocol code" would implement a check that the script size hint provided to the tx kernel matches the size of the FeesI think the impact on fees is that we'd need to reflect the cost of adding the public code to the network plus the hash computations required for insertion into the code tree. Could be via a new base fee or by destructuring the costs into "data" + "computation". PublicCodePatch
If the code is no longer in I think the alternative is to leave the actual code in SummaryTo summarize:
|
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
Currently, we have two issues with how public account/note script code is included in the chain, and it would be good to fix both before mainnet as fixing these after would be quite complicated (if not impossible):
Externalnode, or it could have the full MAST under it.Code commitments
A potential way to address the first issue is to change our code commitment methodology. A key observation here is that MAST of a procedure is fully specified by the procedure root + a set of external nodes in the underlying MAST (cc @huitseeker and @Al-Kindi-0 to double-check me on this). This means, that we can define note script and account code commitments as follows:
Implementing the above shouldn't be too difficult - we would need to update the transaction kernel and all relevant off-chain code, but it shouldn't cause any fundamental issues.
This solves the first problem, but it doesn't solve the second (code duplication), but before I get to a potential way to solve it, let's first look into some other checks that we need to do with the public code.
Code completeness
One of such checks that the node performs is figuring out if the submitted public code can be executed. We can't guarantee this in principle, but we try to make as many checks as possible. For example, we verify that MAST is well-formed. We can also perform one extra check (which I'm not sure if we do now): we could check that we know of all external nodes referenced by a note script or account code. Currently, these would be check against procedures in core and standard library, and for note scripts, also roots of the previously committed note scripts.
But such checks on the node could be potentially expensive - so, it would be great if the user could prove that all external nodes are known to the node. One way to do this is to include a commitment to all known code in the block header. Then, during a transaction, the user would need to make sure all external procedures of their code are covered by this commitment. The commitment could be a simple map:
Where value
1would indicate the a procedure with this root is known to the network.As mentioned above, we'd include this map into the block header - in a way, it could be parallel to account and nullifier trees (we could call it something like
code_tree_root).This tree would be initialized with roots for procedures from the
coreandstandardslibraries, and any time a new note script appears on-chain, it would be added to the tree.Notice that this eliminates the problem of needing to merge note scripts, because for a script to appear on-chain, it needs to prove that all of its dependencies are already on-chain - i.e., there is no way to "hide" a part of the public script from the network (which maybe something we can relax in the future, if needed).
Any time we do a network upgrade, we'd need to populate the tree with the roots of new
coreandstandardslibrary procedures - which I don't think is a problem (and maybe even a good thing). We can also introduce other values beyond0and1to mark some previously introduced procedures as deprecated or forbidden (e.g., due to known bugs).De-duplicating account code
We could apply the above approach to account code as well. Specifically, whenever a new public account gets created, we'd do the following:
Then, all subsequent accounts that export the same procedures could replace already "registered" procedures with
Externalnodes (similar to how we do this with note scripts).The net effect is that the "network code tree" would be a commitment to all code known to the network, and if a procedure is present in this tree, creating a note or an account with such procedures would be very cheap (from code standpoint).
Network code patches
We could take the above a step further and make addition of new code to the "network code tree" explicit. Specifically, we could add a new element to the transaction outputs:
new_code_commitment. This commitment could be a simple sequential hash of procedure roots for procedures that need to be added to the network code tree. These procedures would be identified as follows:This would also imply that the actual MAST code included with transaction would not be in the
AccountCodeorNoteScriptstruct, but rather in a transaction-level object - e.g.,PublicCodePatch. This could look something like:To summarize:
So, any feedback is welcome.
Beta Was this translation helpful? Give feedback.
All reactions