filecoin-project / specs

The Filecoin protocol specification
https://spec.filecoin.io
Other
367 stars 170 forks source link

Paying the storage miner under the offchain repair model #28

Closed whyrusleeping closed 5 years ago

whyrusleeping commented 6 years ago

Since we no longer have funds locked up in on-chain deals for the storage miner, we have to find some way to pay them that provides assurance both to them, and to clients. (Note: 'client' refers to anyone interacting with the storage miner trying to store files. this could be a storage broker, or a non-miner client)

We can start by saying the client must have funds locked up in an open payment channel to the miner up front. A set of pregenerated and presigned updates should be sent to the miner, each of which is time-locked (redeemable only after a specific block height) and contains funds for that time period (if the total agreement is 100 FIL for storing the file for 100 blocks, then you could send ten updates, the first for 10 FIL after 10 blocks, etc). But, they also need to not be valid if the miner isnt storing the data.

Let's look at the different points in the protocol we could send these, and what it would take to ensure the constraints are met.

Note: More complicated payment channel updates can be 'reconciled' by asking the signer for a succinct update. For example, if the miner has finished the agreement, they could go back to the client and ask for a simple payment channel update that invalidates the previous, and is good for the same amount. Allowing the miner to submit a much smaller transaction. This will be effective in the Broker<->Miner scenario, less so in any Client<->Miner one.

Up Front

If the client sends a set of payment channel updates to the miner up-front, along with the initial proposal, they would need to be valid contingent on the miner having a sector committed to disk that provably contains the file the client wants to be stored.

To do this, the redemption of the payment channel update would have to be accompianied by a proof. This proof could be a snark, with a sector ID and the file hash as public inputs. The proof could actually be a snarked version of the proof the miner has to send the client anyways. This amounts to somewhere north of 300 bytes, which is pretty rough. But, if we can assume payment channel reconciliation, that might work. It's also pretty annoying to have to write an extra circuit for this, so let's see if we can do it better

After Data Transfer

After the data is transferred, the miner could finish filling up the sector (but not sealing it) and send the client an inclusion proof of their data within CommD (the merkletree of the un-encrypted sector). If the CommD is part of the public inputs to the seal proof, then the payment channel updates could be contingent on the existence of a valid sector on-chain whose CommD is the agreed upon value.

This is a much cleaner requirement, but:

After Sealing

If the miner waits until after sealing to collect their payment assurance, then they are near-trivially DoSable. It definitely needs to happen before then.

Up Front Take 2

Upon receiving the deal, the miner tells the client a sector ID that their file will be placed at. The client then sends the channel updates along with the data. These proofs can be cashed out at any time after the time period, given that the sector that was agreed upon is still valid on-chain. If the miner does not send the client a valid proof of inclusion after sealing and committing the sector, the client may post the agreement from the miner on-chain as a challenge. This gives the miner a fixed period of time to respond to the challenge with the appropriate proof, or be slashed.

Problem 1: What if the client never sends the file after receiving the promise from the miner, and then posts that promise to the chain as a challenge?

Problem 2: What if the miner makes that promise to the client, and the client is slow? The miner would have to wait for the client to finish their sector and seal it up. Malicious clients might be able to use this to DoS miners.

whyrusleeping commented 6 years ago

I like the 'after data transfer' approach for cases where the client is a broker. Since brokers are staked pretty heavily on-chain, the cost to DoS a miner as a broker is quite high.

For arbitrary clients, I don't think there are any good solutions that don't present DoS vectors. The first 'up front' method could work, but the expense is really annoying, and random clients arent likely to sit around waiting for storage miners to ask them to reconcile their payment channel updates.

whyrusleeping commented 6 years ago

I have a new payment channel construction for Broker<->Miner payments that has nice coalescing and multi-lane payments (can have multiple independent vouchers for different file storage agreements). I'll try and post that early next week after I clean it up a bit.

whyrusleeping commented 6 years ago

From @nicola: CommD does go on chain (unless we do weird aggregation stuff). This makes the 'after data transfer' method much more viable

whyrusleeping commented 6 years ago

Thought: The information required by the miner to cash out a payment channel voucher should contain the data needed by the repair broker to prove they are doing their job correctly. In this case, the way that the repair miner 'challenges' the storage miner for the inclusion proof is by threatening to close the payment channel.

Needs more thought, but if it works out, it should simplify things.

whyrusleeping commented 6 years ago

The initial up-front approach could just be: Payments are contingent on the existence of a sector on-chain from the miner that contains the subtree X, where X is the file in question. The 'proof' here would be a merkleproof, from the sector CommD root to X, for any size of X larger than 1MB, this should be less than 300 bytes, which is reasonable.

whyrusleeping commented 6 years ago

Candidate generalized payments flow for 'payments over time':

Payment validity requirements: To ensure that the miner only gets paid for doing their job, the payment channel updates need to be contingent on some specific parameters. For the inital payments for storage miners, these payments should be contingent on the existence, on-chain, of a sector that can be proved to contain the data in question (via a merkleproof).

whyrusleeping commented 6 years ago

For most cases, the above flow should work for interacting with storage miners. For smaller files, the merkleproof required for submitting the update may be rather large. If that is a problem, we can then introduce another round of interaction in which the miner tells the client about a sector, and shows the client a merklepath from the sectors commD to their data. The client can then send a new set of payment channels with the condition changed to "Sector X exists and is valid".

whyrusleeping commented 6 years ago

For client-repair-miner interactions, the same flow can be used, but the criteria on the updates can be changed to: "There exists a deal on chain that contains (via merklepath) data X". And those can be replaced with "Deal Y exists and is valid" with a successive round of communication.