mirror of
https://github.com/logos-storage/logos-storage-research.git
synced 2026-01-03 05:53:09 +00:00
Draft design for a storage proof network
This commit is contained in:
parent
c18cbef8ff
commit
6b2d7a411f
245
design/proof-network.md
Normal file
245
design/proof-network.md
Normal file
@ -0,0 +1,245 @@
|
||||
Storage proof network
|
||||
=====================
|
||||
|
||||
Authors: Codex Team
|
||||
|
||||
In this document we explore a design for an off-chain network for validating
|
||||
[storage proofs][1]. Instead of checking each storage proof in a smart contract
|
||||
on-chain, we let the proof network check these proofs. Only when a proof is
|
||||
missing we go on-chain to enact slashing. The main goal of this exercise is to
|
||||
reduce the costs of submitting and validating proofs, which has shown to be a
|
||||
limiting factor for the profitability of storage providers and the scaling of
|
||||
the storage network, even when deploying on a [rollup][2] or [sidechain][3].
|
||||
|
||||
[1]: proof-erasure-coding.md
|
||||
[2]: ../evaluations/rollups.md
|
||||
[3]: ../evaluations/sidechains.md
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
The main idea is that validators in the network sign off on messages containing
|
||||
correct storage proofs, and on messages that correctly indicate that a proof is
|
||||
missing. These validators deposit a stake on-chain. We consider a message to be
|
||||
validated by the network when a subset of the validators representing > 2/3 of
|
||||
the total network stake have signed off on it. The assumption here is that less
|
||||
than 1/3 of the validators are byzantine, meaning that the rest is online and
|
||||
following protocol.
|
||||
|
||||
Roles in the network are:
|
||||
|
||||
- provers: they are the storage providers that submit storage proofs
|
||||
- validators: they sign off on submitted proofs and missed proofs
|
||||
- watchers: they monitor for missing proofs, and trigger slashing on-chain
|
||||
|
||||
They are all connected to the same peer-to-peer gossipsub network in which they
|
||||
exchange messsages. The provers and watchers also monitor the on-chain
|
||||
marketplace to check when storage proofs are required.
|
||||
|
||||
|
||||
prover validator
|
||||
|
||||
prover <---------> gossipsub <--------------> validator
|
||||
|
||||
prover ^ | validator
|
||||
\ |
|
||||
\ |
|
||||
\ v watcher
|
||||
\
|
||||
\ watcher
|
||||
\
|
||||
\ ^ watcher
|
||||
\ |
|
||||
\ |
|
||||
\ |
|
||||
\ v
|
||||
|
||||
marketplace
|
||||
(on-chain)
|
||||
|
||||
Messages
|
||||
--------
|
||||
|
||||
The messages that are exchanged over the gossipsub network are:
|
||||
|
||||
- `SubmitProof(slot id, period, inputs, proof)`
|
||||
- `ProofSigned(slot id, period, inputs, signature)`
|
||||
- `ProofValidated(slot id, period, inputs, combined signature)`
|
||||
- `SubmitMissed(slot id, period, inputs)`
|
||||
- `MissedSigned(slot id, period, inputs, signature)`
|
||||
|
||||
A *slot id* parameters refers to a [slot in a storage request][4] on the
|
||||
marketplace. It uniquely identifies the data for which a storage proof is
|
||||
required. The *period* refers to a [time interval][5] in which the storage proof
|
||||
should be submitted. By *proof* we mean a [zero-knowledge proof][5], and by
|
||||
*inputs* we mean its public inputs. A *signature* is a BLS validator signature,
|
||||
and a *combined signature* is a BLS signature that is a combination of multiple
|
||||
validator signatures.
|
||||
|
||||
#### SubmitProof ####
|
||||
|
||||
A prover broadcasts a `SubmitProof` message to indicate to the network that it
|
||||
calculated a storage proof as required by the marketplace.
|
||||
|
||||
#### ProofSigned ####
|
||||
|
||||
A validator broadcasts a `ProofSigned` message in response to a `SubmitProof`
|
||||
message. It only responds with `ProofSigned` after verifying the correctness of
|
||||
the zero knowledge *proof* w.r.t. its public *inputs*, and checking that the
|
||||
time *period* has not ended yet.
|
||||
|
||||
#### ProofValidated ####
|
||||
|
||||
A prover broadcasts `ProofValidated` after it collected enough `ProofSigned`
|
||||
messages from the validators. It combines the BLS *signatures* that it received
|
||||
into a single *combined signature* which represents > 2/3 stake of the network.
|
||||
|
||||
#### SubmitMissed ####
|
||||
|
||||
A watcher broadcasts a `SubmitMissed` when it notices that a required proof was
|
||||
not submitted.
|
||||
|
||||
#### MissedSigned ####
|
||||
|
||||
A validator broadcasts `MissedSigned` only when the *period* has ended, and the
|
||||
validator did not previously broadcast a `ProofSigned` for the same *slot id*,
|
||||
*period* and *inputs*.
|
||||
|
||||
[4]: marketplace.md
|
||||
[5]: https://github.com/codex-storage/codex-storage-proofs-circuits#circuit
|
||||
|
||||
Flows
|
||||
-------
|
||||
|
||||
### Successfull proof submission and validation ###
|
||||
|
||||
Provers monitor the on-chain marketplace to check in which periods they need to
|
||||
provide a storage proof. When a proof is required in the current *period*, the
|
||||
prover gathers public *inputs* for the slot, including the random challenge for
|
||||
the current period and calculates a zero-knowledge storage *proof*. The prover
|
||||
then broadcast `SubmitProof(slot id, period, inputs, proof)`:
|
||||
|
||||
validator
|
||||
SubmitProof
|
||||
prover ---------------------------------------> validator
|
||||
|
||||
validator
|
||||
|
||||
Upon receiving a `SubmitProof` message a validator checks that the *period*
|
||||
hasn't ended yet and that the *proof* is correct w.r.t. to the *inputs*. If that
|
||||
is all in order it will sign and broadcast a `ProofSigned(slot id, period,
|
||||
inputs, signature)` message:
|
||||
|
||||
|
||||
validator
|
||||
ProofSigned
|
||||
prover <--------------------------------------- validator
|
||||
|
||||
validator
|
||||
|
||||
Provers listen for these `ProofSigned` messages from the validators, and once
|
||||
they accumulated enough *signature*s from validators to represent > 2/3 stake,
|
||||
they create a *combined signature* and broadcast `ProofValidated(slot id,
|
||||
period, inputs, combined signature)`:
|
||||
|
||||
ProofValidated
|
||||
prover ------------------.
|
||||
|
|
||||
|
|
||||
v watcher
|
||||
|
||||
watcher
|
||||
|
||||
watcher
|
||||
|
||||
### Missing proofs ###
|
||||
|
||||
Watchers monitor the on-chain marketplace to check which slots require a storage
|
||||
proof to be submitted and what the public *inputs* for the proof are. For each
|
||||
required proof they then monitor the gossipsub network for `ProofValidated`
|
||||
messages. If they do not observe a `ProofValidated` message that is signed by >
|
||||
2/3 stake before the end of the period with the expected *slot id*, *period* and
|
||||
*inputs* parameters, then they will broadcast a `SubmitMissed(slot id, period,
|
||||
inputs)` message.
|
||||
|
||||
validator
|
||||
|
||||
.--------------------> validator
|
||||
|
|
||||
| validator
|
||||
|
|
||||
SubmitMissed |
|
||||
|
|
||||
|
||||
watcher
|
||||
|
||||
Upon receiving a `SubmitMissed(slot id, period, inputs)` message a validator
|
||||
checks that the *period* has ended and that it hasn't already sent out a
|
||||
`ProofSigned` message for the *slot id*, *period* and *inputs*. If it indeed
|
||||
did not, then it will sign and broadcast a `MissedSigned(slot id, period,
|
||||
inputs, signature)`.
|
||||
|
||||
validator
|
||||
MissedSigned
|
||||
.--------------------- validator
|
||||
|
|
||||
| validator
|
||||
|
|
||||
|
|
||||
v
|
||||
|
||||
watcher
|
||||
|
||||
When the watcher receives enough *signature*s to represent > 2/3 stake it can
|
||||
combine these signatures into a single *combined signature*. The watcher can
|
||||
then submit *slot id*, *period*, *inputs* and *combined signature* to the
|
||||
marketplace.
|
||||
|
||||
The marketplace will then verify the correctness of *inputs* for the *slot id*
|
||||
and *period*, and checks that the *combined signature* is representative for >
|
||||
2/3 stake. If these conditions are met, it will then slash the storage provider
|
||||
collateral and reward the watcher.
|
||||
|
||||
### Faulty proofs ###
|
||||
|
||||
The storage proofs that a prover submits can be faulty for a number of reasons:
|
||||
|
||||
1. The zero knowledge *proof* is incorrect
|
||||
2. The submitted *period* is not the current time period
|
||||
3. The public *inputs* to the proof do not match the values from the on-chain
|
||||
marketplace
|
||||
|
||||
Faults 1 and 2 are caught by the validators. Correct validators will not sign
|
||||
off on invalid zero-knowledge *proofs*, or on a *period* that is not the current
|
||||
time period. This means that it is not possible to construct a `ProofValidated`
|
||||
message with a *combined signature* representing > 2/3 stake. Watchers and
|
||||
Validators are now free to treat the proof as missing, and go through the same
|
||||
flow that we described in the previous section.
|
||||
|
||||
Fault 3 is caught by the watchers and the on-chain marketplace. Watchers will
|
||||
look for a `ProofValidated` that has the same *inputs* as specified by the
|
||||
marketplace. If it doesn't find it because the prover broadcast a
|
||||
`ProofValidated` with a different value for *inputs*, then it will treat the proof as missing, and go through the same flow as in the previous section.
|
||||
|
||||
Consensus
|
||||
---------
|
||||
|
||||
The core of our design consists of the fact that correct validators either sign
|
||||
off on a `ProofSigned` message -or- on a `MissedSigned` message, but never on
|
||||
both. We then use a light form of consensus by combining signatures of
|
||||
validators representing > 2/3 stake. Because we assume that there are < 1/3
|
||||
stake byzantine validators, it is always possible to either get enough
|
||||
signatures to validate a correct proof that was submitted on time, or get enough
|
||||
signatures to sign off on a missed or faulty proof.
|
||||
|
||||
There is one scenario in which consensus might not be reached. When a proof is
|
||||
submitted at the end of its time period, and it reached some of the correct
|
||||
validators before the period ends, and some of the correct validators after the
|
||||
period ends. In this scenario it can occur that it's not possible to get enough
|
||||
signatures to validate the proof, and not enough signatures to sign off on a
|
||||
missed proof.
|
||||
|
||||
We argue that is not a problematic scenario for our storage proof network. The
|
||||
prover did provide a correct proof to at least one correct validator, meaning
|
||||
that is still storing the data that it is supposed to. Not being able to slash
|
||||
it in this case is therefore ok.
|
||||
Loading…
x
Reference in New Issue
Block a user