mirror of
https://github.com/status-im/nim-dagger.git
synced 2025-01-10 14:46:03 +00:00
372f827982
Add or remove proof requirements when a request contract’s state changes. When a request sale has completed (for a slot), the host who purchased that slot now must provide regular proofs for the data they are contracted to hold. This is now enforced by adding the slotId to the HashSet of Ids for which to require proofs. When a request has been cancelled (not all slots were filled before the request expired), proofs no longer need to be provided and the slotId is removed from teh HashSet. Add `isCancelled` and `isSlotCancelled` checks to query the contract state without relying the on the state context variable in the contract. Because contract state can only be updated in a transaction, and the client withdrawing funds is responsible for changing the contract state to “Cancelled”, the `isCancelled` and `isSlotCancelled` functions were introduced to check the state regardless of whether or not the client had already withdrawn their funds.
88 lines
2.7 KiB
Nim
88 lines
2.7 KiB
Nim
import std/sets
|
|
import pkg/upraises
|
|
import pkg/questionable
|
|
import pkg/chronicles
|
|
import ./storageproofs
|
|
import ./clock
|
|
|
|
export sets
|
|
export storageproofs
|
|
|
|
type
|
|
Proving* = ref object
|
|
proofs: Proofs
|
|
clock: Clock
|
|
loop: ?Future[void]
|
|
slots*: HashSet[SlotId]
|
|
onProofRequired: ?OnProofRequired
|
|
OnProofRequired* = proc (id: SlotId) {.gcsafe, upraises:[].}
|
|
|
|
func new*(_: type Proving, proofs: Proofs, clock: Clock): Proving =
|
|
Proving(proofs: proofs, clock: clock)
|
|
|
|
proc `onProofRequired=`*(proving: Proving, callback: OnProofRequired) =
|
|
proving.onProofRequired = some callback
|
|
|
|
func add*(proving: Proving, id: SlotId) =
|
|
proving.slots.incl(id)
|
|
|
|
proc getCurrentPeriod(proving: Proving): Future[Period] {.async.} =
|
|
let periodicity = await proving.proofs.periodicity()
|
|
return periodicity.periodOf(proving.clock.now().u256)
|
|
|
|
proc waitUntilPeriod(proving: Proving, period: Period) {.async.} =
|
|
let periodicity = await proving.proofs.periodicity()
|
|
await proving.clock.waitUntil(periodicity.periodStart(period).truncate(int64))
|
|
|
|
proc removeEndedContracts(proving: Proving) {.async.} =
|
|
let now = proving.clock.now().u256
|
|
var ended: HashSet[SlotId]
|
|
for id in proving.slots:
|
|
if now >= (await proving.proofs.getProofEnd(id)):
|
|
ended.incl(id)
|
|
proving.slots.excl(ended)
|
|
|
|
proc removeCancelledContracts(proving: Proving) {.async.} =
|
|
var cancelled: HashSet[ContractId]
|
|
for id in proving.contracts:
|
|
if (await proving.proofs.isSlotCancelled(id)):
|
|
cancelled.incl(id)
|
|
proving.contracts.excl(cancelled)
|
|
|
|
proc run(proving: Proving) {.async.} =
|
|
try:
|
|
while true:
|
|
let currentPeriod = await proving.getCurrentPeriod()
|
|
await proving.removeEndedContracts()
|
|
await proving.removeCancelledContracts()
|
|
for id in proving.slots:
|
|
if (await proving.proofs.isProofRequired(id)) or
|
|
(await proving.proofs.willProofBeRequired(id)):
|
|
if callback =? proving.onProofRequired:
|
|
callback(id)
|
|
await proving.waitUntilPeriod(currentPeriod + 1)
|
|
except CancelledError:
|
|
discard
|
|
except CatchableError as e:
|
|
error "Proving failed", msg = e.msg
|
|
|
|
proc start*(proving: Proving) {.async.} =
|
|
if proving.loop.isSome:
|
|
return
|
|
|
|
proving.loop = some proving.run()
|
|
|
|
proc stop*(proving: Proving) {.async.} =
|
|
if loop =? proving.loop:
|
|
proving.loop = Future[void].none
|
|
if not loop.finished:
|
|
await loop.cancelAndWait()
|
|
|
|
proc submitProof*(proving: Proving, id: SlotId, proof: seq[byte]) {.async.} =
|
|
await proving.proofs.submitProof(id, proof)
|
|
|
|
proc subscribeProofSubmission*(proving: Proving,
|
|
callback: OnProofSubmitted):
|
|
Future[Subscription] =
|
|
proving.proofs.subscribeProofSubmission(callback)
|