-
Notifications
You must be signed in to change notification settings - Fork 241
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
Inconsistency of domain block body and extrinsics root #2181
Comments
My first thought is to combine proposed solutions:
|
In this way, the invalid domain extrinsic root fraud proof issue still exists:
|
As @vedhavyas previously mentioned failed extrinsic will still increase the signer's nonce (thus not fully rollback of the state), I took a closer look and found something new. Essentially, the extrinsic can fail to be executed due to:
In the above code, Thus if an extrinsic itself fails during execution it will still be included in the extrinsic root, but if it fails at There are 2 general solutions for this issue:
|
Ideally, the extrinsics that fail the basic checks should not be included and bundle carrying such should be marked invalid. Shouldn't this be solved once we implement extrinsinc check of extrinsincs in a bundle using single execution context ? |
Not solved completely, because the
Overall, I think the "Eliminate all possible extrinsic that will fail at pre_dispatch/post_dispatch from the domain block" approach is more strict and hard to hold all the time since the abovementioned case may not be exhaustive. |
Hmm. AFAIK, I am leaning towards this solution:
As this mean we do have enough data to re-calculate the extrinsic root correctly as well verification of fraud proof. |
When constructing the domain block, we are using a customized block builder, so that we can build the domain block with the exact extrinsic that derive from the domain bundle. While most of the behaviors of the customized block builder are the same as the upstream one, there is a slight deviation:
In the upstream block builder, only extrinsic that executed successfully will be stored in the block body:
https://github.com/paritytech/polkadot-sdk/blob/2d9426f1cc144a0624ea0329ddc7e567bb47d6b2/substrate/client/block-builder/src/lib.rs#L214-L217
In our customized block builder, all the extrinsic that derive from the domain bundle will be stored in the block body:
https://github.com/subspace/subspace/blob/cf22036f78dd6418f3c71184ffd516dd08e26d32/domains/client/block-builder/src/lib.rs#L288
On both the upstream and our block builder, if an extrinsic return error while executing it, all of the intermediate state generated during the execution will be rollbacked, which includes:
pallet-system
related state, includingExtrinsicData
which is used to compute theextrinsics_root
in the block headerextrinsics_root
ER::execution_trace
This causes an inconsistency of the domain block body and extrinsic root, if we use the domain block body to compute the extrinsic root again, we will get a different extrinsic root compared to the one in the block header. Furthermore, this also causes trouble in the fraud proof:
mismatch_index
of thelocal_er::execution_trace
andexternal_er::execution_trace
to get the extrinsic present atmismatch_index
in the domain block body as the call data, and used it to verify the execution proof, since theER::execution_trace
only store trace for successfully executed extrinsic while the domain block body store all the extrinsic, we could getting the wrong extrinsic as the call dataIf we follow the upstream behavior to only store the successfully executed extrinsic in the block body, the invalid state transition fraud proof issue can be fixed easily. However, the invalid domain extrinsic root fraud proof is difficult to fix, because it needs to use the successfully executed extrinsic to compute the extrinsic root, and it is hard to know whether an extrinsic can be successfully executed without actually executing it (and all other extrinsic in front of it).
Another potential solution is we still keep all the domain extrinsic in the block body, and when an extrinsic returns an error while executing it in our block builder, we only rollback the "state generated while executing the extrinsic itself" and keep the
pallet-system
related state and the execution trace state, this will require further customization for our block builder and will bring more complexity.cc @vedhavyas @ParthDesai @nazar-pc
The text was updated successfully, but these errors were encountered: