[purchasing] Update to latest dagger-contracts

This commit is contained in:
Mark Spanbroek 2022-06-14 15:25:48 +02:00 committed by markspanbroek
parent b7ab9481d9
commit 4b5cfe8e41
3 changed files with 50 additions and 75 deletions

View File

@ -3,6 +3,7 @@ import pkg/chronos
type
Clock* = ref object of RootObj
SecondsSince1970* = int64
Timeout* = object of CatchableError
method now*(clock: Clock): SecondsSince1970 {.base.} =
raiseAssert "not implemented"
@ -10,3 +11,15 @@ method now*(clock: Clock): SecondsSince1970 {.base.} =
proc waitUntil*(clock: Clock, time: SecondsSince1970) {.async.} =
while clock.now() < time:
await sleepAsync(1.seconds)
proc withTimeout*(future: Future[void],
clock: Clock,
expiry: SecondsSince1970) {.async.} =
let timeout = clock.waitUntil(expiry)
try:
await future or timeout
finally:
await timeout.cancelAndWait()
if not future.completed:
await future.cancelAndWait()
raise newException(Timeout, "Timed out")

View File

@ -25,6 +25,7 @@ type
request*: StorageRequest
offers*: seq[StorageOffer]
selected*: ?StorageOffer
PurchaseTimeout* = Timeout
const DefaultProofProbability = 100.u256
const DefaultRequestExpiryInterval = (10 * 60).u256
@ -69,29 +70,30 @@ func getPurchase*(purchasing: Purchasing, id: array[32, byte]): ?Purchase =
else:
none Purchase
proc selectOffer(purchase: Purchase) {.async.} =
var cheapest: ?StorageOffer
for offer in purchase.offers:
without purchase.clock.now().u256 < offer.expiry - purchase.offerExpiryMargin:
continue
without current =? cheapest:
cheapest = some offer
continue
if current.price > offer.price:
cheapest = some offer
if cheapest =? cheapest:
await purchase.market.selectOffer(cheapest.id)
purchase.selected = some cheapest
proc run(purchase: Purchase) {.async.} =
proc onOffer(offer: StorageOffer) =
purchase.offers.add(offer)
let market = purchase.market
purchase.request = await market.requestStorage(purchase.request)
let subscription = await market.subscribeOffers(purchase.request.id, onOffer)
await purchase.clock.waitUntil(purchase.request.expiry.truncate(int64))
await purchase.selectOffer()
await subscription.unsubscribe()
let clock = purchase.clock
proc requestStorage {.async.} =
purchase.request = await market.requestStorage(purchase.request)
proc waitUntilFulfilled {.async.} =
let done = newFuture[void]()
proc callback(_: array[32, byte]) =
done.complete()
let request = purchase.request
let subscription = await market.subscribeFulfillment(request.id, callback)
try:
await done
finally:
await subscription.unsubscribe()
proc withTimeout(future: Future[void]) {.async.} =
let expiry = purchase.request.expiry.truncate(int64)
await future.withTimeout(clock, expiry)
await requestStorage()
await waitUntilFulfilled().withTimeout()
proc start(purchase: Purchase) =
purchase.future = purchase.run()

View File

@ -25,13 +25,8 @@ suite "Purchasing":
)
)
proc purchaseAndWait(request: StorageRequest) {.async.} =
let purchase = purchasing.purchase(request)
clock.set(market.requested[^1].expiry.truncate(int64))
await purchase.wait()
test "submits a storage request when asked":
await purchaseAndWait(request)
discard purchasing.purchase(request)
let submitted = market.requested[0]
check submitted.ask.duration == request.ask.duration
check submitted.ask.size == request.ask.size
@ -48,12 +43,12 @@ suite "Purchasing":
test "can change default value for proof probability":
purchasing.proofProbability = 42.u256
await purchaseAndWait(request)
discard purchasing.purchase(request)
check market.requested[0].ask.proofProbability == 42.u256
test "can override proof probability per request":
request.ask.proofProbability = 42.u256
await purchaseAndWait(request)
discard purchasing.purchase(request)
check market.requested[0].ask.proofProbability == 42.u256
test "has a default value for request expiration interval":
@ -62,66 +57,31 @@ suite "Purchasing":
test "can change default value for request expiration interval":
purchasing.requestExpiryInterval = 42.u256
let start = getTime().toUnix()
await purchaseAndWait(request)
discard purchasing.purchase(request)
check market.requested[0].expiry == (start + 42).u256
test "can override expiry time per request":
let expiry = (getTime().toUnix() + 42).u256
request.expiry = expiry
await purchaseAndWait(request)
discard purchasing.purchase(request)
check market.requested[0].expiry == expiry
test "includes a random nonce in every storage request":
await purchaseAndWait(request)
await purchaseAndWait(request)
discard purchasing.purchase(request)
discard purchasing.purchase(request)
check market.requested[0].nonce != market.requested[1].nonce
proc createOffer(request: StorageRequest): StorageOffer =
StorageOffer(
requestId: request.id,
expiry: (getTime() + initDuration(hours = 1)).toUnix().u256
)
test "selects the cheapest offer":
test "succeeds when request is fulfilled":
let purchase = purchasing.purchase(request)
let request = market.requested[0]
var offer1, offer2 = createOffer(request)
offer1.price = 20.u256
offer2.price = 10.u256
discard await market.offerStorage(offer1)
discard await market.offerStorage(offer2)
clock.set(request.expiry.truncate(int64))
let proof = seq[byte].example
await market.fulfillRequest(request.id, proof)
await purchase.wait()
check purchase.selected == some offer2
check market.selected[0] == offer2.id
check purchase.error.isNone
test "ignores offers that expired":
let expired = (getTime() - initTimeInterval(hours = 1)).toUnix().u256
test "fails when request times out":
let purchase = purchasing.purchase(request)
let request = market.requested[0]
var offer1, offer2 = request.createOffer()
offer1.price = 20.u256
offer2.price = 10.u256
offer2.expiry = expired
discard await market.offerStorage(offer1)
discard await market.offerStorage(offer2)
clock.set(request.expiry.truncate(int64))
await purchase.wait()
check market.selected[0] == offer1.id
test "has a default expiration margin for offers":
check purchasing.offerExpiryMargin != 0.u256
test "ignores offers that are about to expire":
let expiryMargin = purchasing.offerExpiryMargin
let purchase = purchasing.purchase(request)
let request = market.requested[0]
var offer1, offer2 = request.createOffer()
offer1.price = 20.u256
offer2.price = 10.u256
offer2.expiry = getTime().toUnix().u256 + expiryMargin - 1
discard await market.offerStorage(offer1)
discard await market.offerStorage(offer2)
clock.set(request.expiry.truncate(int64))
await purchase.wait()
check market.selected[0] == offer1.id
expect PurchaseTimeout:
await purchase.wait()