From b88561e0903503e897d70deef6587697677a16b6 Mon Sep 17 00:00:00 2001 From: markspanbroek Date: Wed, 13 Apr 2022 18:41:48 +0200 Subject: [PATCH] Subscribe to proof submissions (#83) * Update dagger-contracts * [proving] rename ProofTiming -> Proofs * Update nim-ethers to 0.1.4 * [proving] Subscribe to proof submissions * [proving] support proof submission through the Proving abstraction --- dagger.nimble | 2 +- dagger/contracts.nim | 4 +- dagger/contracts/proofs.nim | 61 +++++++++++++++ dagger/contracts/prooftiming.nim | 40 ---------- dagger/contracts/storage.nim | 5 +- dagger/por/timing/proofs.nim | 51 +++++++++++++ dagger/por/timing/prooftiming.nim | 35 --------- dagger/proving.nim | 28 ++++--- tests/contracts/testContracts.nim | 3 +- tests/contracts/testProofTiming.nim | 47 ------------ tests/contracts/testProofs.nim | 70 ++++++++++++++++++ tests/dagger/helpers/mockproofs.nim | 94 ++++++++++++++++++++++++ tests/dagger/helpers/mockprooftiming.nim | 72 ------------------ tests/dagger/testproving.nim | 67 +++++++++++------ tests/examples.nim | 5 ++ tests/testContracts.nim | 2 +- vendor/dagger-contracts | 2 +- vendor/nim-contract-abi | 2 +- vendor/nim-ethers | 2 +- 19 files changed, 358 insertions(+), 234 deletions(-) create mode 100644 dagger/contracts/proofs.nim delete mode 100644 dagger/contracts/prooftiming.nim create mode 100644 dagger/por/timing/proofs.nim delete mode 100644 dagger/por/timing/prooftiming.nim delete mode 100644 tests/contracts/testProofTiming.nim create mode 100644 tests/contracts/testProofs.nim create mode 100644 tests/dagger/helpers/mockproofs.nim delete mode 100644 tests/dagger/helpers/mockprooftiming.nim diff --git a/dagger.nimble b/dagger.nimble index 96e34907..29e3a2c2 100644 --- a/dagger.nimble +++ b/dagger.nimble @@ -13,7 +13,7 @@ requires "nim >= 1.2.0", "chronicles >= 0.7.2", "chronos >= 2.5.2", "confutils", - "ethers >= 0.1.3 & < 0.2.0", + "ethers >= 0.1.4 & < 0.2.0", "libbacktrace", "libp2p", "metrics", diff --git a/dagger/contracts.nim b/dagger/contracts.nim index 8aed6b0f..fbab0760 100644 --- a/dagger/contracts.nim +++ b/dagger/contracts.nim @@ -3,11 +3,11 @@ import contracts/offers import contracts/storage import contracts/deployment import contracts/market -import contracts/prooftiming +import contracts/proofs export requests export offers export storage export deployment export market -export prooftiming +export proofs diff --git a/dagger/contracts/proofs.nim b/dagger/contracts/proofs.nim new file mode 100644 index 00000000..d6cafc66 --- /dev/null +++ b/dagger/contracts/proofs.nim @@ -0,0 +1,61 @@ +import pkg/ethers +import ../por/timing/proofs +import ./storage + +export proofs + +type + OnChainProofs* = ref object of Proofs + storage: Storage + pollInterval*: Duration + ProofsSubscription = proofs.Subscription + EventSubscription = ethers.Subscription + OnChainProofsSubscription = ref object of ProofsSubscription + eventSubscription: EventSubscription + +const DefaultPollInterval = 3.seconds + +proc new*(_: type OnChainProofs, storage: Storage): OnChainProofs = + OnChainProofs(storage: storage, pollInterval: DefaultPollInterval) + +method periodicity*(proofs: OnChainProofs): Future[Periodicity] {.async.} = + let period = await proofs.storage.proofPeriod() + return Periodicity(seconds: period) + +method getCurrentPeriod*(proofs: OnChainProofs): Future[Period] {.async.} = + let periodicity = await proofs.periodicity() + let blk = !await proofs.storage.provider.getBlock(BlockTag.latest) + return periodicity.periodOf(blk.timestamp) + +method waitUntilPeriod*(proofs: OnChainProofs, + period: Period) {.async.} = + while (await proofs.getCurrentPeriod()) < period: + await sleepAsync(proofs.pollInterval) + +method isProofRequired*(proofs: OnChainProofs, + id: ContractId): Future[bool] {.async.} = + return await proofs.storage.isProofRequired(id) + +method willProofBeRequired*(proofs: OnChainProofs, + id: ContractId): Future[bool] {.async.} = + return await proofs.storage.willProofBeRequired(id) + +method getProofEnd*(proofs: OnChainProofs, + id: ContractId): Future[UInt256] {.async.} = + return await proofs.storage.proofEnd(id) + +method submitProof*(proofs: OnChainProofs, + id: ContractId, + proof: seq[byte]) {.async.} = + await proofs.storage.submitProof(id, proof) + +method subscribeProofSubmission*(proofs: OnChainProofs, + callback: OnProofSubmitted): + Future[ProofsSubscription] {.async.} = + proc onEvent(event: ProofSubmitted) {.upraises: [].} = + callback(event.id, event.proof) + let subscription = await proofs.storage.subscribe(ProofSubmitted, onEvent) + return OnChainProofsSubscription(eventSubscription: subscription) + +method unsubscribe*(subscription: OnChainProofsSubscription) {.async, upraises:[].} = + await subscription.eventSubscription.unsubscribe() diff --git a/dagger/contracts/prooftiming.nim b/dagger/contracts/prooftiming.nim deleted file mode 100644 index 3688c634..00000000 --- a/dagger/contracts/prooftiming.nim +++ /dev/null @@ -1,40 +0,0 @@ -import ../por/timing/prooftiming -import ./storage - -export prooftiming - -type - OnChainProofTiming* = ref object of ProofTiming - storage: Storage - pollInterval*: Duration - -const DefaultPollInterval = 3.seconds - -proc new*(_: type OnChainProofTiming, storage: Storage): OnChainProofTiming = - OnChainProofTiming(storage: storage, pollInterval: DefaultPollInterval) - -method periodicity*(timing: OnChainProofTiming): Future[Periodicity] {.async.} = - let period = await timing.storage.proofPeriod() - return Periodicity(seconds: period) - -method getCurrentPeriod*(timing: OnChainProofTiming): Future[Period] {.async.} = - let periodicity = await timing.periodicity() - let blk = !await timing.storage.provider.getBlock(BlockTag.latest) - return periodicity.periodOf(blk.timestamp) - -method waitUntilPeriod*(timing: OnChainProofTiming, - period: Period) {.async.} = - while (await timing.getCurrentPeriod()) < period: - await sleepAsync(timing.pollInterval) - -method isProofRequired*(timing: OnChainProofTiming, - id: ContractId): Future[bool] {.async.} = - return await timing.storage.isProofRequired(id) - -method willProofBeRequired*(timing: OnChainProofTiming, - id: ContractId): Future[bool] {.async.} = - return await timing.storage.willProofBeRequired(id) - -method getProofEnd*(timing: OnChainProofTiming, - id: ContractId): Future[UInt256] {.async.} = - return await timing.storage.proofEnd(id) diff --git a/dagger/contracts/storage.nim b/dagger/contracts/storage.nim index eeba433f..85fd9385 100644 --- a/dagger/contracts/storage.nim +++ b/dagger/contracts/storage.nim @@ -21,6 +21,9 @@ type OfferSelected* = object of Event offerId*: Id requestId* {.indexed.}: Id + ProofSubmitted* = object of Event + id*: Id + proof*: seq[byte] proc collateralAmount*(storage: Storage): UInt256 {.contract, view.} proc slashMisses*(storage: Storage): UInt256 {.contract, view.} @@ -47,5 +50,5 @@ proc willProofBeRequired*(storage: Storage, id: Id): bool {.contract, view.} proc getChallenge*(storage: Storage, id: Id): array[32, byte] {.contract, view.} proc getPointer*(storage: Storage, id: Id): uint8 {.contract, view.} -proc submitProof*(storage: Storage, id: Id, proof: bool) {.contract.} +proc submitProof*(storage: Storage, id: Id, proof: seq[byte]) {.contract.} proc markProofAsMissing*(storage: Storage, id: Id, period: UInt256) {.contract.} diff --git a/dagger/por/timing/proofs.nim b/dagger/por/timing/proofs.nim new file mode 100644 index 00000000..13da7c17 --- /dev/null +++ b/dagger/por/timing/proofs.nim @@ -0,0 +1,51 @@ +import pkg/chronos +import pkg/stint +import pkg/upraises +import ./periods + +export chronos +export stint +export periods + +type + Proofs* = ref object of RootObj + Subscription* = ref object of RootObj + OnProofSubmitted* = proc(id: ContractId, proof: seq[byte]) {.gcsafe, upraises:[].} + ContractId* = array[32, byte] + +method periodicity*(proofs: Proofs): + Future[Periodicity] {.base, async.} = + raiseAssert("not implemented") + +method getCurrentPeriod*(proofs: Proofs): + Future[Period] {.base, async.} = + raiseAssert("not implemented") + +method waitUntilPeriod*(proofs: Proofs, + period: Period) {.base, async.} = + raiseAssert("not implemented") + +method isProofRequired*(proofs: Proofs, + id: ContractId): Future[bool] {.base, async.} = + raiseAssert("not implemented") + +method willProofBeRequired*(proofs: Proofs, + id: ContractId): Future[bool] {.base, async.} = + raiseAssert("not implemented") + +method getProofEnd*(proofs: Proofs, + id: ContractId): Future[UInt256] {.base, async.} = + raiseAssert("not implemented") + +method submitProof*(proofs: Proofs, + id: ContractId, + proof: seq[byte]) {.base, async.} = + raiseAssert("not implemented") + +method subscribeProofSubmission*(proofs: Proofs, + callback: OnProofSubmitted): + Future[Subscription] {.base, async.} = + raiseAssert("not implemented") + +method unsubscribe*(subscription: Subscription) {.base, async, upraises:[].} = + raiseAssert("not implemented") diff --git a/dagger/por/timing/prooftiming.nim b/dagger/por/timing/prooftiming.nim deleted file mode 100644 index 54d3e03a..00000000 --- a/dagger/por/timing/prooftiming.nim +++ /dev/null @@ -1,35 +0,0 @@ -import pkg/chronos -import pkg/stint -import ./periods - -export chronos -export stint -export periods - -type - ProofTiming* = ref object of RootObj - ContractId* = array[32, byte] - -method periodicity*(proofTiming: ProofTiming): - Future[Periodicity] {.base, async.} = - raiseAssert("not implemented") - -method getCurrentPeriod*(proofTiming: ProofTiming): - Future[Period] {.base, async.} = - raiseAssert("not implemented") - -method waitUntilPeriod*(proofTiming: ProofTiming, - period: Period) {.base, async.} = - raiseAssert("not implemented") - -method isProofRequired*(proofTiming: ProofTiming, - id: ContractId): Future[bool] {.base, async.} = - raiseAssert("not implemented") - -method willProofBeRequired*(proofTiming: ProofTiming, - id: ContractId): Future[bool] {.base, async.} = - raiseAssert("not implemented") - -method getProofEnd*(proofTiming: ProofTiming, - id: ContractId): Future[UInt256] {.base, async.} = - raiseAssert("not implemented") diff --git a/dagger/proving.nim b/dagger/proving.nim index 945de5c0..e013658c 100644 --- a/dagger/proving.nim +++ b/dagger/proving.nim @@ -2,21 +2,21 @@ import std/sets import std/times import pkg/upraises import pkg/questionable -import ./por/timing/prooftiming +import ./por/timing/proofs export sets -export prooftiming +export proofs type Proving* = ref object - timing: ProofTiming + proofs: Proofs stopped: bool contracts*: HashSet[ContractId] onProofRequired: ?OnProofRequired OnProofRequired* = proc (id: ContractId) {.gcsafe, upraises:[].} -func new*(_: type Proving, timing: ProofTiming): Proving = - Proving(timing: timing) +func new*(_: type Proving, proofs: Proofs): Proving = + Proving(proofs: proofs) proc `onProofRequired=`*(proving: Proving, callback: OnProofRequired) = proving.onProofRequired = some callback @@ -28,23 +28,31 @@ proc removeEndedContracts(proving: Proving) {.async.} = let now = getTime().toUnix().u256 var ended: HashSet[ContractId] for id in proving.contracts: - if now >= (await proving.timing.getProofEnd(id)): + if now >= (await proving.proofs.getProofEnd(id)): ended.incl(id) proving.contracts.excl(ended) proc run(proving: Proving) {.async.} = while not proving.stopped: - let currentPeriod = await proving.timing.getCurrentPeriod() + let currentPeriod = await proving.proofs.getCurrentPeriod() await proving.removeEndedContracts() for id in proving.contracts: - if (await proving.timing.isProofRequired(id)) or - (await proving.timing.willProofBeRequired(id)): + if (await proving.proofs.isProofRequired(id)) or + (await proving.proofs.willProofBeRequired(id)): if callback =? proving.onProofRequired: callback(id) - await proving.timing.waitUntilPeriod(currentPeriod + 1) + await proving.proofs.waitUntilPeriod(currentPeriod + 1) proc start*(proving: Proving) = asyncSpawn proving.run() proc stop*(proving: Proving) = proving.stopped = true + +proc submitProof*(proving: Proving, id: ContractId, proof: seq[byte]) {.async.} = + await proving.proofs.submitProof(id, proof) + +proc subscribeProofSubmission*(proving: Proving, + callback: OnProofSubmitted): + Future[Subscription] = + proving.proofs.subscribeProofSubmission(callback) diff --git a/tests/contracts/testContracts.nim b/tests/contracts/testContracts.nim index 5104e8ee..bee55fb0 100644 --- a/tests/contracts/testContracts.nim +++ b/tests/contracts/testContracts.nim @@ -71,10 +71,11 @@ ethersuite "Storage contracts": check proofEnd > 0 test "accept storage proofs": + let proof = seq[byte].example switchAccount(host) await storage.startContract(id) await waitUntilProofRequired(id) - await storage.submitProof(id, true) + await storage.submitProof(id, proof) test "can mark missing proofs": switchAccount(host) diff --git a/tests/contracts/testProofTiming.nim b/tests/contracts/testProofTiming.nim deleted file mode 100644 index 2e6fa3c4..00000000 --- a/tests/contracts/testProofTiming.nim +++ /dev/null @@ -1,47 +0,0 @@ -import ./ethertest -import dagger/contracts -import ./examples -import ./time - -ethersuite "On-Chain Proof Timing": - - var timing: OnChainProofTiming - var storage: Storage - - setup: - let deployment = deployment() - storage = Storage.new(!deployment.address(Storage), provider) - timing = OnChainProofTiming.new(storage) - - test "can retrieve proof periodicity": - let periodicity = await timing.periodicity() - let periodLength = await storage.proofPeriod() - check periodicity.seconds == periodLength - - test "supports waiting until next period": - let periodicity = await timing.periodicity() - let currentPeriod = await timing.getCurrentPeriod() - - let pollInterval = 200.milliseconds - timing.pollInterval = pollInterval - - proc waitForPoll {.async.} = - await sleepAsync(pollInterval * 2) - - let future = timing.waitUntilPeriod(currentPeriod + 1) - - check not future.completed - - await provider.advanceTimeTo(periodicity.periodEnd(currentPeriod)) - await waitForPoll() - - check future.completed - - test "supports checking whether proof is required now": - check (await timing.isProofRequired(ContractId.example)) == false - - test "supports checking whether proof is required soon": - check (await timing.willProofBeRequired(ContractId.example)) == false - - test "retrieves proof end time": - check (await timing.getProofEnd(ContractId.example)) == 0.u256 diff --git a/tests/contracts/testProofs.nim b/tests/contracts/testProofs.nim new file mode 100644 index 00000000..2633487f --- /dev/null +++ b/tests/contracts/testProofs.nim @@ -0,0 +1,70 @@ +import ./ethertest +import dagger/contracts +import ./examples +import ./time + +ethersuite "On-Chain Proofs": + + let contractId = ContractId.example + let proof = seq[byte].example + + var proofs: OnChainProofs + var storage: Storage + + setup: + let deployment = deployment() + storage = Storage.new(!deployment.address(Storage), provider.getSigner()) + proofs = OnChainProofs.new(storage) + + test "can retrieve proof periodicity": + let periodicity = await proofs.periodicity() + let periodLength = await storage.proofPeriod() + check periodicity.seconds == periodLength + + test "supports waiting until next period": + let periodicity = await proofs.periodicity() + let currentPeriod = await proofs.getCurrentPeriod() + + let pollInterval = 200.milliseconds + proofs.pollInterval = pollInterval + + proc waitForPoll {.async.} = + await sleepAsync(pollInterval * 2) + + let future = proofs.waitUntilPeriod(currentPeriod + 1) + + check not future.completed + + await provider.advanceTimeTo(periodicity.periodEnd(currentPeriod)) + await waitForPoll() + + check future.completed + + test "supports checking whether proof is required now": + check (await proofs.isProofRequired(contractId)) == false + + test "supports checking whether proof is required soon": + check (await proofs.willProofBeRequired(contractId)) == false + + test "retrieves proof end time": + check (await proofs.getProofEnd(contractId)) == 0.u256 + + test "submits proofs": + await proofs.submitProof(contractId, proof) + + test "supports proof submission subscriptions": + var receivedIds: seq[ContractId] + var receivedProofs: seq[seq[byte]] + + proc onProofSubmission(id: ContractId, proof: seq[byte]) = + receivedIds.add(id) + receivedProofs.add(proof) + + let subscription = await proofs.subscribeProofSubmission(onProofSubmission) + + await proofs.submitProof(contractId, proof) + + check receivedIds == @[contractId] + check receivedProofs == @[proof] + + await subscription.unsubscribe() diff --git a/tests/dagger/helpers/mockproofs.nim b/tests/dagger/helpers/mockproofs.nim new file mode 100644 index 00000000..152b8420 --- /dev/null +++ b/tests/dagger/helpers/mockproofs.nim @@ -0,0 +1,94 @@ +import std/sets +import std/tables +import std/sequtils +import pkg/upraises +import pkg/dagger/por/timing/proofs + +type + MockProofs* = ref object of Proofs + periodicity: Periodicity + currentPeriod: Period + waiting: Table[Period, seq[Future[void]]] + proofsRequired: HashSet[ContractId] + proofsToBeRequired: HashSet[ContractId] + proofEnds: Table[ContractId, UInt256] + subscriptions: seq[MockSubscription] + MockSubscription* = ref object of Subscription + proofs: MockProofs + callback: OnProofSubmitted + +const DefaultPeriodLength = 10.u256 + +func new*(_: type MockProofs): MockProofs = + MockProofs(periodicity: Periodicity(seconds: DefaultPeriodLength)) + +func setPeriodicity*(mock: MockProofs, periodicity: Periodicity) = + mock.periodicity = periodicity + +method periodicity*(mock: MockProofs): Future[Periodicity] {.async.} = + return mock.periodicity + +proc setProofRequired*(mock: MockProofs, id: ContractId, required: bool) = + if required: + mock.proofsRequired.incl(id) + else: + mock.proofsRequired.excl(id) + +method isProofRequired*(mock: MockProofs, + id: ContractId): Future[bool] {.async.} = + return mock.proofsRequired.contains(id) + +proc setProofToBeRequired*(mock: MockProofs, id: ContractId, required: bool) = + if required: + mock.proofsToBeRequired.incl(id) + else: + mock.proofsToBeRequired.excl(id) + +method willProofBeRequired*(mock: MockProofs, + id: ContractId): Future[bool] {.async.} = + return mock.proofsToBeRequired.contains(id) + +proc setProofEnd*(mock: MockProofs, id: ContractId, proofEnd: UInt256) = + mock.proofEnds[id] = proofEnd + +method getProofEnd*(mock: MockProofs, + id: ContractId): Future[UInt256] {.async.} = + if mock.proofEnds.hasKey(id): + return mock.proofEnds[id] + else: + return UInt256.high + +proc advanceToPeriod*(mock: MockProofs, period: Period) = + doAssert period >= mock.currentPeriod + for key in mock.waiting.keys: + if key <= period: + for future in mock.waiting[key]: + future.complete() + mock.waiting[key] = @[] + +method getCurrentPeriod*(mock: MockProofs): Future[Period] {.async.} = + return mock.currentPeriod + +method waitUntilPeriod*(mock: MockProofs, period: Period) {.async.} = + if period > mock.currentPeriod: + let future = Future[void]() + if not mock.waiting.hasKey(period): + mock.waiting[period] = @[] + mock.waiting[period].add(future) + await future + +method submitProof*(mock: MockProofs, + id: ContractId, + proof: seq[byte]) {.async.} = + for subscription in mock.subscriptions: + subscription.callback(id, proof) + +method subscribeProofSubmission*(mock: MockProofs, + callback: OnProofSubmitted): + Future[Subscription] {.async.} = + let subscription = MockSubscription(proofs: mock, callback: callback) + mock.subscriptions.add(subscription) + return subscription + +method unsubscribe*(subscription: MockSubscription) {.async, upraises:[].} = + subscription.proofs.subscriptions.keepItIf(it != subscription) diff --git a/tests/dagger/helpers/mockprooftiming.nim b/tests/dagger/helpers/mockprooftiming.nim deleted file mode 100644 index 3ab7fe6c..00000000 --- a/tests/dagger/helpers/mockprooftiming.nim +++ /dev/null @@ -1,72 +0,0 @@ -import std/sets -import std/tables -import pkg/dagger/por/timing/prooftiming - -type - MockProofTiming* = ref object of ProofTiming - periodicity: Periodicity - currentPeriod: Period - waiting: Table[Period, seq[Future[void]]] - proofsRequired: HashSet[ContractId] - proofsToBeRequired: HashSet[ContractId] - proofEnds: Table[ContractId, UInt256] - -const DefaultPeriodLength = 10.u256 - -func new*(_: type MockProofTiming): MockProofTiming = - MockProofTiming(periodicity: Periodicity(seconds: DefaultPeriodLength)) - -func setPeriodicity*(mock: MockProofTiming, periodicity: Periodicity) = - mock.periodicity = periodicity - -method periodicity*(mock: MockProofTiming): Future[Periodicity] {.async.} = - return mock.periodicity - -proc setProofRequired*(mock: MockProofTiming, id: ContractId, required: bool) = - if required: - mock.proofsRequired.incl(id) - else: - mock.proofsRequired.excl(id) - -method isProofRequired*(mock: MockProofTiming, - id: ContractId): Future[bool] {.async.} = - return mock.proofsRequired.contains(id) - -proc setProofToBeRequired*(mock: MockProofTiming, id: ContractId, required: bool) = - if required: - mock.proofsToBeRequired.incl(id) - else: - mock.proofsToBeRequired.excl(id) - -method willProofBeRequired*(mock: MockProofTiming, - id: ContractId): Future[bool] {.async.} = - return mock.proofsToBeRequired.contains(id) - -proc setProofEnd*(mock: MockProofTiming, id: ContractId, proofEnd: UInt256) = - mock.proofEnds[id] = proofEnd - -method getProofEnd*(mock: MockProofTiming, - id: ContractId): Future[UInt256] {.async.} = - if mock.proofEnds.hasKey(id): - return mock.proofEnds[id] - else: - return UInt256.high - -proc advanceToPeriod*(mock: MockProofTiming, period: Period) = - doAssert period >= mock.currentPeriod - for key in mock.waiting.keys: - if key <= period: - for future in mock.waiting[key]: - future.complete() - mock.waiting[key] = @[] - -method getCurrentPeriod*(mock: MockProofTiming): Future[Period] {.async.} = - return mock.currentPeriod - -method waitUntilPeriod*(mock: MockProofTiming, period: Period) {.async.} = - if period > mock.currentPeriod: - let future = Future[void]() - if not mock.waiting.hasKey(period): - mock.waiting[period] = @[] - mock.waiting[period].add(future) - await future diff --git a/tests/dagger/testproving.nim b/tests/dagger/testproving.nim index 79c4fb35..159fb732 100644 --- a/tests/dagger/testproving.nim +++ b/tests/dagger/testproving.nim @@ -2,25 +2,25 @@ from std/times import getTime, toUnix import pkg/asynctest import pkg/chronos import pkg/dagger/proving -import ./helpers/mockprooftiming +import ./helpers/mockproofs import ./examples suite "Proving": var proving: Proving - var timing: MockProofTiming + var proofs: MockProofs setup: - timing = MockProofTiming.new() - proving = Proving.new(timing) + proofs = MockProofs.new() + proving = Proving.new(proofs) proving.start() teardown: proving.stop() - proc advanceToNextPeriod(timing: MockProofTiming) {.async.} = - let current = await timing.getCurrentPeriod() - timing.advanceToPeriod(current + 1) + proc advanceToNextPeriod(proofs: MockProofs) {.async.} = + let current = await proofs.getCurrentPeriod() + proofs.advanceToPeriod(current + 1) await sleepAsync(1.milliseconds) test "maintains a list of contract ids to watch": @@ -45,8 +45,8 @@ suite "Proving": proc onProofRequired(id: ContractId) = called = true proving.onProofRequired = onProofRequired - timing.setProofRequired(id, true) - await timing.advanceToNextPeriod() + proofs.setProofRequired(id, true) + await proofs.advanceToNextPeriod() check called test "callback receives id of contract for which proof is required": @@ -57,12 +57,12 @@ suite "Proving": proc onProofRequired(id: ContractId) = callbackIds.add(id) proving.onProofRequired = onProofRequired - timing.setProofRequired(id1, true) - await timing.advanceToNextPeriod() + proofs.setProofRequired(id1, true) + await proofs.advanceToNextPeriod() check callbackIds == @[id1] - timing.setProofRequired(id1, false) - timing.setProofRequired(id2, true) - await timing.advanceToNextPeriod() + proofs.setProofRequired(id1, false) + proofs.setProofRequired(id2, true) + await proofs.advanceToNextPeriod() check callbackIds == @[id1, id2] test "invokes callback when proof is about to be required": @@ -72,20 +72,45 @@ suite "Proving": proc onProofRequired(id: ContractId) = called = true proving.onProofRequired = onProofRequired - timing.setProofRequired(id, false) - timing.setProofToBeRequired(id, true) - await timing.advanceToNextPeriod() + proofs.setProofRequired(id, false) + proofs.setProofToBeRequired(id, true) + await proofs.advanceToNextPeriod() check called test "stops watching when contract has ended": let id = ContractId.example proving.add(id) - timing.setProofEnd(id, getTime().toUnix().u256) - await timing.advanceToNextPeriod() + proofs.setProofEnd(id, getTime().toUnix().u256) + await proofs.advanceToNextPeriod() var called: bool proc onProofRequired(id: ContractId) = called = true proving.onProofRequired = onProofRequired - timing.setProofRequired(id, true) - await timing.advanceToNextPeriod() + proofs.setProofRequired(id, true) + await proofs.advanceToNextPeriod() check not called + + test "submits proofs": + let id = ContractId.example + let proof = seq[byte].example + await proving.submitProof(id, proof) + + test "supports proof submission subscriptions": + let id = ContractId.example + let proof = seq[byte].example + + var receivedIds: seq[ContractId] + var receivedProofs: seq[seq[byte]] + + proc onProofSubmission(id: ContractId, 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() diff --git a/tests/examples.nim b/tests/examples.nim index 63994083..933fc990 100644 --- a/tests/examples.nim +++ b/tests/examples.nim @@ -1,4 +1,5 @@ import std/random +import std/sequtils import pkg/stint proc example*[T: SomeInteger](_: type T): T = @@ -8,5 +9,9 @@ proc example*[T,N](_: type array[N, T]): array[N, T] = for item in result.mitems: item = T.example +proc example*[T](_: type seq[T]): seq[T] = + let length = uint8.example.int + newSeqWith(length, T.example) + proc example*(_: type UInt256): UInt256 = UInt256.fromBytes(array[32, byte].example) diff --git a/tests/testContracts.nim b/tests/testContracts.nim index 30a4bd5b..1ef8ca5d 100644 --- a/tests/testContracts.nim +++ b/tests/testContracts.nim @@ -1,6 +1,6 @@ import ./contracts/testCollateral import ./contracts/testContracts import ./contracts/testMarket -import ./contracts/testProofTiming +import ./contracts/testProofs {.warning[UnusedImport]:off.} diff --git a/vendor/dagger-contracts b/vendor/dagger-contracts index 6aa28945..2bf01da7 160000 --- a/vendor/dagger-contracts +++ b/vendor/dagger-contracts @@ -1 +1 @@ -Subproject commit 6aa2894521faa53a9896e800caf713499b33c318 +Subproject commit 2bf01da728317fd1f3ae8424785f31b53eb4013f diff --git a/vendor/nim-contract-abi b/vendor/nim-contract-abi index 0d9a25ec..b111c27b 160000 --- a/vendor/nim-contract-abi +++ b/vendor/nim-contract-abi @@ -1 +1 @@ -Subproject commit 0d9a25ec0ab9c4b807664a357c7ec31006986cae +Subproject commit b111c27b619fc1d81fb1c6942372824a18a71960 diff --git a/vendor/nim-ethers b/vendor/nim-ethers index ac74b91f..a0dca267 160000 --- a/vendor/nim-ethers +++ b/vendor/nim-ethers @@ -1 +1 @@ -Subproject commit ac74b91f11bb8511ab9e7cc3075f0267415c3006 +Subproject commit a0dca2674d07b34c293ca318fa8ca30e123c13ca