nim-codex/tests/codex/testproving.nim
markspanbroek 4175689745
Load purchase state from chain (#283)
* [purchasing] Simplify test

* [utils] Move StorageRequest.example up one level

* [purchasing] Load purchases from market

* [purchasing] load purchase states

* Implement myRequest() and getState() methods for OnChainMarket

* [proofs] Fix intermittently failing tests

Ensures that examples of proofs in tests are never of length 0;
these are considered invalid proofs by the smart contract logic.

* [contracts] Fix failing test

With the new solidity contracts update, a contract can only
be paid out after it started.

* [market] Add method to get request end time

* [purchasing] wait until purchase is finished

Purchase.wait() would previously wait until purchase
was started, now we wait until it is finished.

* [purchasing] Handle 'finished' and 'failed' states

* [marketplace] move to failed state once request fails

- Add support for subscribing to request failure events.
- Add supporting contract tests for subscribing to request failure events.
- Allow the PurchaseStarted state to move to PurchaseFailure once a request failure event is emitted
- Add supporting tests for moving from PurchaseStarted to PurchaseFailure
- Add state transition tests for PurchaseUnknown.

* [marketplace] Fix test with longer sleepAsync

* [integration] Add function to restart a codex node

* [purchasing] Set client address before requesting storage

To prevent the purchase id (which equals the request id)
from changing once it's been submitted.

* [contracts] Fix: OnChainMarket.getState()

Had the wrong method signature before

* [purchasing] Load purchases on node start

* [purchasing] Rename state 'PurchaseError' to 'PurchaseErrored'

Allows for an exception type called 'PurchaseError'

* [purchasing] Load purchases in background

No longer calls market.getRequest() for every purchase
on node start.

* [contracts] Add `$` for RequestId, SlotId and Nonce

To aid with debugging

* [purchasing] Add Purchasing.stop()

To ensure that all contract interactions have both a
start() and a stop() for

* [tests] Remove sleepAsync where possible

Use `eventually` loop instead, to make sure that we're
not waiting unnecessarily.

* [integration] Fix: handle non-json response in test

* [purchasing] Add purchase state to json

* [integration] Ensure that purchase is submitted before restart

Fixes test failure on slower CI

* [purchasing] re-implement `description` as method

Allows description to be set in the same module where the
state type is defined.

Co-authored-by: Eric Mastro <eric.mastro@gmail.com>

* [contracts] fix typo

Co-authored-by: Eric Mastro <eric.mastro@gmail.com>

* [market] Use more generic error type

Should we decide to change the provider type later

Co-authored-by: Eric Mastro <eric.mastro@gmail.com>

Co-authored-by: Eric Mastro <eric.mastro@gmail.com>
2022-11-08 08:10:17 +01:00

120 lines
3.3 KiB
Nim

import pkg/asynctest
import pkg/chronos
import pkg/codex/proving
import ./helpers/mockproofs
import ./helpers/mockclock
import ./helpers/eventually
import ./examples
suite "Proving":
var proving: Proving
var proofs: MockProofs
var clock: MockClock
setup:
proofs = MockProofs.new()
clock = MockClock.new()
proving = Proving.new(proofs, clock)
await proving.start()
teardown:
await proving.stop()
proc advanceToNextPeriod(proofs: MockProofs) {.async.} =
let periodicity = await proofs.periodicity()
clock.advance(periodicity.seconds.truncate(int64))
test "maintains a list of contract ids to watch":
let id1, id2 = SlotId.example
check proving.slots.len == 0
proving.add(id1)
check proving.slots.contains(id1)
proving.add(id2)
check proving.slots.contains(id1)
check proving.slots.contains(id2)
test "removes duplicate contract ids":
let id = SlotId.example
proving.add(id)
proving.add(id)
check proving.slots.len == 1
test "invokes callback when proof is required":
let id = SlotId.example
proving.add(id)
var called: bool
proc onProofRequired(id: SlotId) =
called = true
proving.onProofRequired = onProofRequired
proofs.setProofRequired(id, true)
await proofs.advanceToNextPeriod()
check eventually called
test "callback receives id of contract for which proof is required":
let id1, id2 = SlotId.example
proving.add(id1)
proving.add(id2)
var callbackIds: seq[SlotId]
proc onProofRequired(id: SlotId) =
callbackIds.add(id)
proving.onProofRequired = onProofRequired
proofs.setProofRequired(id1, true)
await proofs.advanceToNextPeriod()
check eventually callbackIds == @[id1]
proofs.setProofRequired(id1, false)
proofs.setProofRequired(id2, true)
await proofs.advanceToNextPeriod()
check eventually callbackIds == @[id1, id2]
test "invokes callback when proof is about to be required":
let id = SlotId.example
proving.add(id)
var called: bool
proc onProofRequired(id: SlotId) =
called = true
proving.onProofRequired = onProofRequired
proofs.setProofRequired(id, false)
proofs.setProofToBeRequired(id, true)
await proofs.advanceToNextPeriod()
check eventually called
test "stops watching when contract has ended":
let id = SlotId.example
proving.add(id)
proofs.setProofEnd(id, clock.now().u256)
await proofs.advanceToNextPeriod()
var called: bool
proc onProofRequired(id: SlotId) =
called = true
proving.onProofRequired = onProofRequired
proofs.setProofRequired(id, true)
await proofs.advanceToNextPeriod()
check eventually (not proving.slots.contains(id))
check not called
test "submits proofs":
let id = SlotId.example
let proof = exampleProof()
await proving.submitProof(id, proof)
test "supports proof submission subscriptions":
let id = SlotId.example
let proof = exampleProof()
var receivedIds: seq[SlotId]
var receivedProofs: seq[seq[byte]]
proc onProofSubmission(id: SlotId, proof: seq[byte]) =
receivedIds.add(id)
receivedProofs.add(proof)
let subscription = await proving.subscribeProofSubmission(onProofSubmission)
await proving.submitProof(id, proof)
check receivedIds == @[id]
check receivedProofs == @[proof]
await subscription.unsubscribe()