nim-codex/dagger/proving.nim
markspanbroek 03fa370624
Proving (#66)
* Add Proving object, which maintains contract id's to watch

* [proving] invoke callback when proof is required

# Conflicts:
#	dagger/por/timing/periods.nim
#	dagger/por/timing/prooftiming.nim

* [proving] check proof requirements for all our contracts

# Conflicts:
#	tests/dagger/helpers/mockprooftiming.nim

* Update vendor/dagger-contracts

* [proving] call onProofRequired() when proof is required soon

* [proving] stop checking contracts that have ended

* [proving] Remove duplicated funcs

* [proving] Implement ProofTiming on top of smart contract

* [proving] Fix race condition in waitUntilNextPeriod()

Sometimes waitUntilNextPeriod would take a while to
determine the current period, leading to unexpected results.

Splits waitUntilNextPeriod() into getCurrentPeriod()
and waitUntilPeriod(), to ensure that we're really waiting
for the period that we think we're waiting for.
2022-04-08 15:58:16 -06:00

51 lines
1.4 KiB
Nim

import std/sets
import std/times
import pkg/upraises
import pkg/questionable
import ./por/timing/prooftiming
export sets
export prooftiming
type
Proving* = ref object
timing: ProofTiming
stopped: bool
contracts*: HashSet[ContractId]
onProofRequired: ?OnProofRequired
OnProofRequired* = proc (id: ContractId) {.gcsafe, upraises:[].}
func new*(_: type Proving, timing: ProofTiming): Proving =
Proving(timing: timing)
proc `onProofRequired=`*(proving: Proving, callback: OnProofRequired) =
proving.onProofRequired = some callback
func add*(proving: Proving, id: ContractId) =
proving.contracts.incl(id)
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)):
ended.incl(id)
proving.contracts.excl(ended)
proc run(proving: Proving) {.async.} =
while not proving.stopped:
let currentPeriod = await proving.timing.getCurrentPeriod()
await proving.removeEndedContracts()
for id in proving.contracts:
if (await proving.timing.isProofRequired(id)) or
(await proving.timing.willProofBeRequired(id)):
if callback =? proving.onProofRequired:
callback(id)
await proving.timing.waitUntilPeriod(currentPeriod + 1)
proc start*(proving: Proving) =
asyncSpawn proving.run()
proc stop*(proving: Proving) =
proving.stopped = true