d56eb6aee1
* [contracts] Add SlotFreed event * [integration] allow test node to be stopped twice * [cli] add --validator option * [contracts] remove dead code * [contracts] instantiate OnChainMarket and OnChainClock only once * [contracts] add Validation * [sales] remove duplicate import * [market] add missing import * [market] subscribe to all SlotFilled events * [market] add freeSlot() * [sales] fix warnings * [market] subscribe to SlotFreed events * [contracts] fix warning * [validator] keep track of filled slots * [validation] remove slots that have ended * [proving] absorb Proofs into Market Both Proofs and Market are abstractions around the Marketplace contract, having them separately is more trouble than it's worth at the moment. * [market] add markProofAsMissing() * [clock] speed up waiting for clock in tests * [validator] mark proofs as missing * [timer] fix error on node shutdown * [cli] handle --persistence and --validator separately * [market] allow retrieval of proof timeout value * [validator] do not subscribe to SlotFreed events Freed slots are already handled in removeSlotsThatHaveEnded(), and onSlotsFreed() interfered with its iterator. * [validator] Start validation at the start of a new period To decrease the likelihood that we hit the validation timeout. * [validator] do not mark proofs as missing after timeout * [market] check whether proof can be marked as missing * [validator] simplify validation Simulate a transaction to mark proof as missing, instead of trying to keep track of all the conditions that may lead to a proof being marked as missing. * [build] use nim-ethers PR #40 Uses "pending" blocktag instead of "latest" blocktag for better simulation of transactions before sending them. https://github.com/status-im/nim-ethers/pull/40 * [integration] integration test for validator * [validator] monitor a maximum number of slots Adds cli parameter --validator-max-slots. * [market] fix missing collateral argument After rebasing, add the new argument to fillSlot calls. * [build] update to nim-ethers 0.2.5 * [validator] use Set instead of Table to keep track of slots * [validator] add logging * [validator] add test for slot failure * [market] use "pending" blocktag to use more up to date block time * [contracts] remove unused import * [validator] fix: wait until after period ends The smart contract checks that 'end < block.timestamp', so we need to wait until the block timestamp is greater than the period end. |
||
---|---|---|
.. | ||
interactions | ||
Readme.md | ||
clock.nim | ||
config.nim | ||
deployment.nim | ||
interactions.nim | ||
market.nim | ||
marketplace.nim | ||
requests.nim |
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)