2022-05-19 19:56:03 +00:00
|
|
|
Codex Contracts in Nim
|
2022-03-15 09:40:30 +00:00
|
|
|
=======================
|
|
|
|
|
2022-05-19 19:56:03 +00:00
|
|
|
Nim API for the [Codex smart contracts][1].
|
2022-03-15 09:40:30 +00:00
|
|
|
|
|
|
|
Usage
|
|
|
|
-----
|
|
|
|
|
|
|
|
For a global overview of the steps involved in starting and fulfilling a
|
2022-05-19 19:56:03 +00:00
|
|
|
storage contract, see [Codex Contracts][1].
|
2022-03-15 09:40:30 +00:00
|
|
|
|
|
|
|
Smart contract
|
|
|
|
--------------
|
|
|
|
|
|
|
|
Connecting to the smart contract on an Ethereum node:
|
|
|
|
|
|
|
|
```nim
|
2022-05-19 19:56:03 +00:00
|
|
|
import codex/contracts
|
2022-03-15 09:40:30 +00:00
|
|
|
import ethers
|
|
|
|
|
|
|
|
let address = # fill in address where the contract was deployed
|
|
|
|
let provider = JsonRpcProvider.new("ws://localhost:8545")
|
2023-01-19 05:58:04 +00:00
|
|
|
let marketplace = Marketplace.new(address, provider)
|
2022-03-15 09:40:30 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
Setup client and host so that they can sign transactions; here we use the first
|
|
|
|
two accounts on the Ethereum node:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
let accounts = await provider.listAccounts()
|
|
|
|
let client = provider.getSigner(accounts[0])
|
|
|
|
let host = provider.getSigner(accounts[1])
|
|
|
|
```
|
|
|
|
|
|
|
|
Storage requests
|
|
|
|
----------------
|
|
|
|
|
|
|
|
Creating a request for storage:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
let request : StorageRequest = (
|
|
|
|
client: # address of the client requesting storage
|
|
|
|
duration: # duration of the contract in seconds
|
|
|
|
size: # size in bytes
|
|
|
|
contentHash: # SHA256 hash of the content that's going to be stored
|
|
|
|
proofProbability: # require a storage proof roughly once every N periods
|
|
|
|
maxPrice: # maximum price the client is willing to pay
|
|
|
|
expiry: # expiration time of the request (in unix time)
|
|
|
|
nonce: # random nonce to differentiate between similar requests
|
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
When a client wants to submit this request to the network, it needs to pay the
|
|
|
|
maximum price to the smart contract in advance. The difference between the
|
2023-03-30 09:34:38 +00:00
|
|
|
maximum price and the offered price will be reimbursed later.
|
2022-03-15 09:40:30 +00:00
|
|
|
|
|
|
|
Once the payment has been prepared, the client can submit the request to the
|
|
|
|
network:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
await storage
|
|
|
|
.connect(client)
|
|
|
|
.requestStorage(request)
|
|
|
|
```
|
|
|
|
|
|
|
|
Storage offers
|
|
|
|
--------------
|
|
|
|
|
|
|
|
Creating a storage offer:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
let offer: StorageOffer = (
|
|
|
|
host: # address of the host that is offering storage
|
|
|
|
requestId: request.id,
|
|
|
|
price: # offered price (in number of tokens)
|
|
|
|
expiry: # expiration time of the offer (in unix time)
|
|
|
|
)
|
|
|
|
```
|
|
|
|
|
|
|
|
Hosts submits an offer:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
await storage
|
|
|
|
.connect(host)
|
|
|
|
.offerStorage(offer)
|
|
|
|
```
|
|
|
|
|
|
|
|
Client selects an offer:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
await storage
|
|
|
|
.connect(client)
|
|
|
|
.selectOffer(offer.id)
|
|
|
|
```
|
|
|
|
|
|
|
|
Starting and finishing a storage contract
|
|
|
|
-----------------------------------------
|
|
|
|
|
|
|
|
The host whose offer got selected can start the storage contract once it
|
|
|
|
received the data that needs to be stored:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
await storage
|
|
|
|
.connect(host)
|
|
|
|
.startContract(offer.id)
|
|
|
|
```
|
|
|
|
|
|
|
|
Once the storage contract is finished, the host can release payment:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
await storage
|
|
|
|
.connect(host)
|
|
|
|
.finishContract(id)
|
|
|
|
```
|
|
|
|
|
|
|
|
Storage proofs
|
|
|
|
--------------
|
|
|
|
|
|
|
|
Time is divided into periods, and each period a storage proof may be required
|
|
|
|
from the host. The odds of requiring a storage proof are negotiated through the
|
|
|
|
storage request. For more details about the timing of storage proofs, please
|
2023-03-30 09:34:38 +00:00
|
|
|
refer to the [design document][2].
|
2022-03-15 09:40:30 +00:00
|
|
|
|
|
|
|
At the start of each period of time, the host can check whether a storage proof
|
|
|
|
is required:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
let isProofRequired = await storage.isProofRequired(offer.id)
|
|
|
|
```
|
|
|
|
|
|
|
|
If a proof is required, the host can submit it before the end of the period:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
await storage
|
|
|
|
.connect(host)
|
|
|
|
.submitProof(id, proof)
|
|
|
|
```
|
|
|
|
|
|
|
|
If a proof is not submitted, then a validator can mark a proof as missing:
|
|
|
|
|
|
|
|
```nim
|
|
|
|
await storage
|
|
|
|
.connect(validator)
|
|
|
|
.markProofAsMissing(id, period)
|
|
|
|
```
|
|
|
|
|
2023-01-19 05:58:04 +00:00
|
|
|
[1]: https://github.com/status-im/codex-contracts-eth/
|
2023-03-30 09:34:38 +00:00
|
|
|
[2]: https://github.com/status-im/codex-research/blob/main/design/storage-proof-timing.md
|