owned this note
owned this note
Published
Linked with GitHub
# Bounty Contract
## Short Intro
:mag: **Problem definition**: Users of a given blockchain (the "host chain") want to use one or more Decentralized Storage Networks (DSNs) to store data.
And specifically, the clients want to use a DSN *without interacting with it*. So, our question is: how can we provide host chain clients with DSN access and storage guarantees directly from/on the host chain?
:bulb: **Proposed solution**: To provide such a service we design a protocol where a third party, the *Storage Dealer*, acts as an intermediary between the client end the DSN. We envision this protocol in this way:
<!---
need to set up a bounty protocol that can check the actual storage (over time) of files on a Decentralized Storage Network. We also need to release a bounty for the service provided, according to a payment policy which makes the service delivery profitable (and thus rational to pursue).
--->
1. Besides host chain client, there is a set of storage dealers that are users of the host chain;
2. On the host chain there is a *Bounty Contract* that clients use to propose a "Bounty Deal" for requesting to store files on a DSN (specifying the "bounty" payment and the duration for storage and optionally other features);
4. [optional] Dealers accept the deal and commit to provide evidence that the file has been stored on the selected DSN according with the terms specified by the client;
5. There is a *Storage Oracle* which can provide a statement that given files are marked as stored on the DSN;
8. The bounty is released to the dealer as soon as it post on the host chain the oracle statement.
In the following section we expand on the high-level overview above, providing full details.
## Protocol Description
### Parties:
- **Host Chain Clients**: An Host Chain Client is the user of our protocol. He wants to store a file on a DSN without interacting with it, but having the same guarantees as a DSN user. To do so the client creates a *Bounty Deal Proposal* on the host chain specifying the file to be stored, the DSN to be used, the bounty that will be paid and other terms and conditions (see below for the full description of the proposal).
<!---
The counterparty could eventually be asked to put down a collateral that will be slashed in case of not being compliant with the storage deal conditions (more details will be provided in the next section).
--->
- **Storage Dealers**: In our protocol, a Storage Dealer is the party that can read the host chain (eg, it has an host chain node) and can store files in a DSN (eg, it has access to the DSN as user or it is one of the node forming the DSN). And, after posting and storage proof on the chain (see next bullet point) can claim the bounty (or part of it).
[Optional] When accepting a deal proposal, a dealer can be asked to put down a collateral as a guarantee for the storage service. This means that this collateral will be taken if the terms specified in the accepted deal are not respected.
<!---
Moreover,
- Each dealer has a list of DSNs that he works with.
- Given a DSN, each dealer has a *dealer policy* with parameters like:
- the `min_bounty`: minimum reward per day per byte,
- the `max_size`: maximum file size accepted in a proposal
- the `max_duration`: maximum duration accepted in a proposal
--->
<!--- - The default values are `min_price`= 0, `max_rate` = TBD, and `max_size`= TBD.
--->
Note that the dealer needs to provide evidence in the host chain about its activity on the DSN. To take care of this, we introduce the following entity:
- **Storage Oracle**: The Storage Oracle takes care of providing the evidence that a file is stored on a specific DSN. And this evidence can be used by the dealer to claim the bounty. More precisely,
- The oracle is invoked ~~from the host chain~~ specifying a `file_id`;
- Once invoked, the oracle checks the DSN to see if there is the evidence of the file corresponding to `file_id` be stored on the DSN at time `T` (the exact functioning of this depends on the DSN);
- If the evidence is found, the oracle sings and sends back ~~on the host chain~~ its signed statement;
- `CallOracle(file_id) --> sig(file_id, T)`
- **Smart Contract** and **Blockchain**: the smart contract contains the logic to create and accept the bounty deal proposal, release bounties and eventually slash dealers.
Note, we assume that a filesharing tool that can make the file available from the client to the storage dealer is used (eg, this can be done via IPFS).
### SLA:
The protocol aims to boost the use of decentralized storage networks for storage over time.
A client using our protocol to store a file on a DSN is guaranteed that it will pay for the storage service (to the dealer) if and only if there is the evidence of file be stored throughout the agreed period of time (according to an agreed check in schedule).
<!---
**Note:** The bounty release mechanism is yet to be design in details. Nevertheless, we identified two different options that can taken into account:
- Release the entire bounty at deal expiration
- This is the safest option for the Host Chain Client (who will pay if and only if storage is successful over time, until the end of the deal), but it is not ideal for the honest dealers who will only get paid at the very end of the service.
- Release the bounty at each successful storage check step.
- We'd have to design an ad hoc release function (with the released bounty fraction growing over time).
- This is not ideal for the client, since a dealer can skip storage checks from one point onwards, without losing the entire bounty. On the other hand, this approach is more fair for honest dealers.
--->
### Bounty Contract:
#### Create Deal Proposal
`createDealProposal(data_uri, duration, bounty) -> deal_id`
The host chain client proposes a bounty deal with the following inputs and conditions:
- The identifier of the file (or folder of files), `data_uri`;
- ~~The list of DSNs that he want to store the file(s) on;~~ [edit: we will have one contract per network]
- ~~The list of the dealers that can redeem the bounty (if no address is specified we consider this to be open, meaning that the bounty can be obtained by any dealer who has the required proofs);~~ [edit: the list of dealers is specified in the smart contract];
- ~~The `oracle addresses`: the list of addresses that can send the storage statement messages;~~ [edit: the `oracle addresses` is specified in the smart contract];
- The `duration`: period of time for which the files has to be stored, from when storage begins (ie, the first oracle statement is posted). Note that there may be a maximum for this value specified by the smart contract;
- The `proving schedule`: it specifies which is the frequency at which the oracle statement has to be posted (eg, every day or only once at the end of duration). We refer to this events as `storage check-in`(s);
- Note: to simplify we assume that there is global `proving schedule` for the smart contract and the client does not have to specify this.
- The `payment`: "bounty", total amount (in native tokens) paid by the client to the dealer (if the deal is not invalidated by lacking of an oracle statement); at the moment of the request creation, the `payment` is "locked down" (ie, taken from the client's account and deposited to the smart contract);
- The `bounty release function`: it describes the dynamics of the bounty release. For example:
- The bounty is released over time at each storage check-in;
- Or the bounty is released at the end of the duration, if all the storage check-ins were successful.
- [optional] The `collateral`: amount (in native tokens) required to be locked down from the dealer.
- As we noted for the `proving schedule`, we may assume that there is a global `realease function` used in the smart contract and clients do not have to care about specifying this.
#### Cancel Deal Proposal
A client can cancel a proposal (not accepted yet) at any time, and this action will release the `payment`.
Moreover, proposals have a timeout after which they are not valid anymore (ie, can not be accepted).
#### Accept Deal Proposal
`acceptDealProposal(uint256 deal_id, string data_uri)`
A dealer can accept the terms specified in a proposal if all the following is true:
- It is one of the dealers in the sc dealer list ~~(or the proposal was open)~~;
- The proposal is active (no timeout, no cancel message);
- [optional] It has enough balance in his account in order to cover for the `collateral` (if collateral is needed). In this case, the `collateral` is "locked down" (ie, from the Storage Dealer's account deposited to the smart contract).
After a dealer has accepted, we say there is an active *Bounty Deal* between the dealer who accepted and the client who crated the deal proposal.
Also, we timestamp this on-chain, and we consider the deal active from this moment onward (`timestamp_start`).
<!---
**Comment about the dealer CLI:** Before automatically accepting a Storage Deal proposal, the following conditions are checked:
- the file is of size `file_size` and `file_size` <= `max_size`;
- the bounty value is larger or equal to `min_price * file_size * duration`;
- the collateral value is smaller of equal to `max_rate * bounty`.
--->
<!--
:::info
Note that:
- If more that one dealer is listed in the proposal by the client, each one of them has to accept the terms individually; each dealer that has accepted can later on claim the bounty;
- Open question: if the proposal is an open one (no dealer listed), how do we deal with multiple dealers accepting? For example: only the first x ones can accept and can claim the bounty?
:::
-->
#### Claim Bounty
`claimBounty(deal_id, data_uri, signature)`
This function can be called by a dealer according to the `bounty release schedule`.
At each call, the function does the following
- Check the schedule to see it the call is expected;
- Check if the deal has been accepted by the caller (ie, check is there is an active deal);
- Check the Oracle's `signature`
- If valid, the deal is maintained active and if there is any due payment (see `release function`), this is deposited to the dealer's account from the smart contract vault.
- Otherwise, the deal is terminated (the remaining part of the bounty is release back to the client, eventually the dealer is slashed).
:::info
Open question: can we handle the "no proof" case in a more flexible way?
- for example, instead of immediate termination, after how many missing proofs we terminate? How this this missing proofs are distributed, consecutive missing proofs or any?
:::
### List of events in the smart contract:
1. `DealProposalCreated(uint256 index, StorageNetworks[], DealersAddress[] OracleAddress[], Duration, BountyAmount, ProvingSchedule, ReleaseFunction, CollateralAddress)`: Event emitted when new deal proposal is created by the client;
2. `DealAccepted(uint256 index)`: Event emitted when a bounty deal is created by a dealer accepting the terms of a proposal (defines `timestamp_start`);
3. `DealProposalCanceled(uint256 index)`: Event emitted when a proposal is canceled by the client before being accepted;
4. `DealInvalidated(uint256 index)`: Event emitted when a bounty deal is invalidated (ie no expected valid oracle proof, according to the proving frequency);
5. `BountyRedeemed(uint256 index)`: Event emitted when a bounty (or part of it) is redeemed by the dealer.
<!---
### Storage Oracle
A Storage Dealer invokes the Storage Oracle every time storage over time must be proven on the host chain, according to the `proving policy`. To do so, one of the `oracle addresses` specified in the deal creates a storage proof and the Storage Oracle Proof.
## Protocol Parameters
- $m_O$ (`oracle multiplier`): the amount (in native tokens) `oracle_fee` = $m_O$ x `bounty` is paid to the referees each time that an oracle query is made; Note that $m_O$ should depend on the proving frequency.
- Why we need this? To reward Oracle parties
- $m_s$ (`slashing_multiplier`): the amount (in native tokens) `slashing_multiplier x bounty` is the maximum of the collateral that a client can ask for.
- `max_oracle_queries`: maximum number of oracle queries per deal; current value is set to TBD [**check if we need it**];
- `proposal_timeout`: timeout to accept a deal proposal (1 week), set to 86400 seconds (1 week).
- `min_duration`: minimum duration of a deal (in days), set to TBD.
- `max_duration`: maximum duration of a deal (in days) TBD.
--->