nim-codex/codex/contracts
Eric de88fd2c53
feat: create logging proxy (#663)
* implement a logging proxy

The logging proxy:
- prevents the need to import chronicles (as well as export except toJson),
- prevents the need to override `writeValue` or use or import nim-json-seralization elsewhere in the codebase, allowing for sole use of utils/json for de/serialization,
- and handles json formatting correctly in chronicles json sinks

* Rename logging -> logutils to avoid ambiguity with common names

* clean up

* add setProperty for JsonRecord, remove nim-json-serialization conflict

* Allow specifying textlines and json format separately

Not specifying a LogFormat will apply the formatting to both textlines and json sinks.

Specifying a LogFormat will apply the formatting to only that sink.

* remove unneeded usages of std/json

We only need to import utils/json instead of std/json

* move serialization from rest/json to utils/json so it can be shared

* fix NoColors ambiguity

Was causing unit tests to fail on Windows.

* Remove nre usage to fix Windows error

Windows was erroring with `could not load: pcre64.dll`. Instead of fixing that error, remove the pcre usage :)

* Add logutils module doc

* Shorten logutils.formatIt for `NBytes`

Both json and textlines formatIt were not needed, and could be combined into one formatIt

* remove debug integration test config

debug output and logformat of json for integration test logs

* Use ## module doc to support docgen

* bump nim-poseidon2 to export fromBytes

Before the changes in this branch, fromBytes was likely being resolved by nim-stew, or other dependency. With the changes in this branch, that dependency was removed and fromBytes could no longer be resolved. By exporting fromBytes from nim-poseidon, the correct resolution is now happening.

* fixes to get compiling after rebasing master

* Add support for Result types being logged using formatIt
2024-01-22 23:35:03 -08:00
..
interactions feat: create logging proxy (#663) 2024-01-22 23:35:03 -08:00
Readme.md feat: collateral per slot (#390) 2023-04-14 11:04:17 +02:00
clock.nim bump ethers, remove upraises from callbacks (#664) 2024-01-09 15:51:34 +11:00
config.nim feat: collateral per slot (#390) 2023-04-14 11:04:17 +02:00
deployment.nim feat: create logging proxy (#663) 2024-01-22 23:35:03 -08:00
interactions.nim Validator (#387) 2023-04-19 15:06:00 +02:00
market.nim feat: create logging proxy (#663) 2024-01-22 23:35:03 -08:00
marketplace.nim Add get active slot /slots/{slotId} to REST api, use utils/json (#645) 2023-12-07 12:16:36 +11:00
requests.nim feat: create logging proxy (#663) 2024-01-22 23:35:03 -08:00

Readme.md

Codex Contracts in Nim

Nim API for the Codex smart contracts.

Usage

For a global overview of the steps involved in starting and fulfilling a storage contract, see Codex Contracts.

Smart contract

Connecting to the smart contract on an Ethereum node:

import codex/contracts
import ethers

let address = # fill in address where the contract was deployed
let provider = JsonRpcProvider.new("ws://localhost:8545")
let marketplace = Marketplace.new(address, provider)

Setup client and host so that they can sign transactions; here we use the first two accounts on the Ethereum node:

let accounts = await provider.listAccounts()
let client = provider.getSigner(accounts[0])
let host = provider.getSigner(accounts[1])

Storage requests

Creating a request for storage:

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 maximum price and the offered price will be reimbursed later.

Once the payment has been prepared, the client can submit the request to the network:

await storage
  .connect(client)
  .requestStorage(request)

Storage offers

Creating a storage offer:

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:

await storage
  .connect(host)
  .offerStorage(offer)

Client selects an offer:

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:

await storage
  .connect(host)
  .startContract(offer.id)

Once the storage contract is finished, the host can release payment:

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 refer to the design document.

At the start of each period of time, the host can check whether a storage proof is required:

let isProofRequired = await storage.isProofRequired(offer.id)

If a proof is required, the host can submit it before the end of the period:

await storage
  .connect(host)
  .submitProof(id, proof)

If a proof is not submitted, then a validator can mark a proof as missing:

await storage
  .connect(validator)
  .markProofAsMissing(id, period)