autonomys / subspace

Subspace Network reference implementation
https://subspace.network
369 stars 242 forks source link

Upgradable fraud proof verification and ER derivation #2712

Open NingLin-P opened 4 months ago

NingLin-P commented 4 months ago

The fraud proof is essentially proof of the ER derivation process and it is proving something happened in the past. Both fraud proof verification and ER derivation MUST keep consistency otherwise the attacker can possibly submit FP to target valid ER (produced by the honest operator) or submit bad ER that can't targeted by FP.

Since the FP is proving something happened in the past we must use both the data and logic from the past, while we already use storage proof of the historical domain state and domain runtime code and working on storage proof of the consensus state, there is one important missing piece which is the consensus runtime.

The logic of the FP verification and ER derivation that involved consensus runtime can fall into the following categories:

  1. The logic exists in both the consensus runtime and the operator client, the code is different but will return the same result (e.g. inherent extrinsic order)
    • Can easily cause inconsistency if we update the logic in one place but forget another (like the extrinsic order we found in 3h)
  2. The logic exists in a shared crate that is used by both the consensus runtime and the operator client (e.g. extrinsic deduplicate and shuffle)
    • Better than 1 but can still cause inconsistency in practice, since runtime upgrade is done automatically while client upgrade is not, can cause honest operators who didn't upgrade get slash.
  3. The logic only exists in the consensus runtime and the operator needs to call the consensus runtime API (e.g. tx-range, consensus transaction byte fee)
    • Better than 2 but still have issues, because the FP is verified against the best block which means the latest consensus runtime is used, while FP is proving something happened in the past so the historical consensus runtime should be used, otherwise, after the consensus runtime logic is upgraded the attacker can submit FP to target ER that produced previously with old runtime by the honest operator.

3 is the best we have so far and we should convert 1 & 2 into 3, to fix the remaining issue of 3 we can:

Another better approach is to introduce a dedicated lightweight runtime, which only contains the necessary logic for FP verification and ER derivation, it can be stored in the consensus chain and can be upgraded just like the domain runtime. Also, storage proof of the runtime code can be replaced by storage proof of the runtime hash in most cases, since runtime upgrade is rare we can get the runtime code from the latest state just need to ensure it has the same hash.

cc @vedhavyas @nazar-pc

dariolina commented 4 months ago

This feels a duplicate of https://github.com/subspace/subspace/issues/2082 however the discussion there may not be relevant anymore since we have MMR now. UPD: this not duplicate but separate issues

nazar-pc commented 4 months ago

I think I agree with general conclusion, but the question still remains where to get the correct consensus runtime. Since it is technically just state as well, we could have MMR proof that something was a valid consensus runtime in the past, but attaching it as part of the proof both constrains the size of consensus runtime and the size of domain storage proof that domain can use, both of which are not ideal.

NingLin-P commented 3 months ago

There are 2 things we can do to reduce the size:

  1. Use the compressed consensus runtime code
    864K    ../../target/release/wbuild/subspace-runtime/subspace_runtime.compact.compressed.wasm
    4.1M    ../../target/release/wbuild/subspace-runtime/subspace_runtime.compact.wasm
    3.6M    ../../target/release/wbuild/subspace-runtime/subspace_runtime.wasm
  2. Extract the necessary logic related to FP verification and ER derivation to a dedicated lightweight runtime

This runtime can be stored and upgraded just like the domain runtime but can't be instantiated like them, this runtime only used in 2 places: