How to generate the extrinsic execution proof #10783
Replies: 3 comments 18 replies
-
This should basically fails in the moment you have multiple extrinsics reading and then writing the same storage entry, because the value is then found in the overlay. As you already have found out, accessing the overlay isn't found in the proof, because it doesn't need to. For your use case, you would require to commit all the intermediate state into a trie and then generate the proof based on this. |
Beta Was this translation helpful? Give feedback.
-
Briefly the idea is that in Subspace we have optimistic execution and fraud proofs. To make fraud proofs efficient for resource-constrained farmers (consensus nodes, they don't execute transactions), fraud proof doesn't cover the whole block, instead it only needs to cover the first transaction which is executed incorrectly in the block. For this to work we need to collect execution trace (effective state roots after every transaction), then in fraud proof we can provide inputs to a particular transaction and correct state root and farmers can just run that one transaction to verify a fraud proof. When compared to Polkadot, the biggest differences are:
|
Beta Was this translation helpful? Give feedback.
-
Can you explain what the dispute covers? It's some storage even like a node serving the wrong data? I'd think bad nodes would simply not serve the data when requested. We knew about partial block fraud proofs when we designed substrate and polkadot, well the fraud proofs paper gave us the erasure coding idea. We decided slashing failed disputes, and punishing both sides on indeterminate disputes, worked out much simpler than partial block fraud proofs. We later noticed partial block fraud proofs break too many optimizations, including cryptographic ones like pre-batching Schnorr or Groth16, SnarkPack, etc. It'll work out differently if you want end users verifying everything of course, like LazyLedger / Celestia or the fraud proofs paper. We also believe this whole approach fails though, due to a tragedy of the commons, maybe details could alter this conclusion, but overall sounds tricky. I do advise deeper consideration over whether partial block fraud proofs really do what you think they do. All this said.. I do believe greater room for optimism exists in when doing storage work, so yeah maybe another approach makes sense here. I'd likely focus upon erasure coding but maybe that brings other annoyances. Also state channels, not sure. We've only really have one sort of storage and proof in substrate, which fits poorly with many important situations. As a prime example, any parachain doing zk UTXOs must implement this all themselves. It's kinda par for the course that if you need to so something interesting then you may require stranger validation code somehow. We should keep teams who run into this sort of things talking together and with us, maybe some shared abstractions emerge, but who knows.. |
Beta Was this translation helpful? Give feedback.
-
Basically, substrate already supports the block execution proof, which is being used to validate the state transition of parachain block in polkadot.
What we want is the more fine-grained extrinsic execution proof in subspace, we use a custom executive (related: #10711) for collecting the storage root after initializing block and applying each extrinsic. If any executor, who is responsible for processing the transactions in subspace, kind of the collator in parachain, detects an invalid state transition of an extrinsic based on the collected intermediate storage roots, then the executor will generate a proof for this invalid extrinsic state transaction, which is the extrinsic execution proof.
My initial idea is that perhaps it might work if we refer to the pattern of the block execution proof, which means to generate the extrinsic proof by using
api.record_proof()
before applying the extrinsic andapi.extract_proof()
after applying the extrinsic, forapi.record_proof()
will reset the innerrecorder
to the default that is sort of a reset.substrate/primitives/api/proc-macro/src/impl_runtime_apis.rs
Lines 274 to 276 in 4cd2cc9
This approach partially works until I found that if there are two same kind of extrinsics in a block, the generated proof will be just empty and finally I think it's probably caused by the overlay when retrieving the storage from the state:
substrate/primitives/state-machine/src/ext.rs
Lines 185 to 189 in a2ae8a5
The reason is that the underlying
ProofRecorder
only exists in the backend not in the overlay, if a storage item already exists in the overlay, then it won't be recorded during the execution of next round, thus the storage proof for the extrinsic execution can't be constructed as expected.In order to support the extrinsic execution proof, we need to also embed a proof recorder in the overlay, something like that. I'm not sure if that's possible and how many efforts are required in substrate. Collect me if I'm wrong, any inputs are appreciated!
Beta Was this translation helpful? Give feedback.
All reactions