[purchasing] Update to latest dagger-contracts
This commit is contained in:
parent
b7ab9481d9
commit
4b5cfe8e41
|
@ -3,6 +3,7 @@ import pkg/chronos
|
||||||
type
|
type
|
||||||
Clock* = ref object of RootObj
|
Clock* = ref object of RootObj
|
||||||
SecondsSince1970* = int64
|
SecondsSince1970* = int64
|
||||||
|
Timeout* = object of CatchableError
|
||||||
|
|
||||||
method now*(clock: Clock): SecondsSince1970 {.base.} =
|
method now*(clock: Clock): SecondsSince1970 {.base.} =
|
||||||
raiseAssert "not implemented"
|
raiseAssert "not implemented"
|
||||||
|
@ -10,3 +11,15 @@ method now*(clock: Clock): SecondsSince1970 {.base.} =
|
||||||
proc waitUntil*(clock: Clock, time: SecondsSince1970) {.async.} =
|
proc waitUntil*(clock: Clock, time: SecondsSince1970) {.async.} =
|
||||||
while clock.now() < time:
|
while clock.now() < time:
|
||||||
await sleepAsync(1.seconds)
|
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")
|
||||||
|
|
|
@ -25,6 +25,7 @@ type
|
||||||
request*: StorageRequest
|
request*: StorageRequest
|
||||||
offers*: seq[StorageOffer]
|
offers*: seq[StorageOffer]
|
||||||
selected*: ?StorageOffer
|
selected*: ?StorageOffer
|
||||||
|
PurchaseTimeout* = Timeout
|
||||||
|
|
||||||
const DefaultProofProbability = 100.u256
|
const DefaultProofProbability = 100.u256
|
||||||
const DefaultRequestExpiryInterval = (10 * 60).u256
|
const DefaultRequestExpiryInterval = (10 * 60).u256
|
||||||
|
@ -69,29 +70,30 @@ func getPurchase*(purchasing: Purchasing, id: array[32, byte]): ?Purchase =
|
||||||
else:
|
else:
|
||||||
none Purchase
|
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 run(purchase: Purchase) {.async.} =
|
||||||
proc onOffer(offer: StorageOffer) =
|
|
||||||
purchase.offers.add(offer)
|
|
||||||
let market = purchase.market
|
let market = purchase.market
|
||||||
purchase.request = await market.requestStorage(purchase.request)
|
let clock = purchase.clock
|
||||||
let subscription = await market.subscribeOffers(purchase.request.id, onOffer)
|
|
||||||
await purchase.clock.waitUntil(purchase.request.expiry.truncate(int64))
|
proc requestStorage {.async.} =
|
||||||
await purchase.selectOffer()
|
purchase.request = await market.requestStorage(purchase.request)
|
||||||
await subscription.unsubscribe()
|
|
||||||
|
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) =
|
proc start(purchase: Purchase) =
|
||||||
purchase.future = purchase.run()
|
purchase.future = purchase.run()
|
||||||
|
|
|
@ -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":
|
test "submits a storage request when asked":
|
||||||
await purchaseAndWait(request)
|
discard purchasing.purchase(request)
|
||||||
let submitted = market.requested[0]
|
let submitted = market.requested[0]
|
||||||
check submitted.ask.duration == request.ask.duration
|
check submitted.ask.duration == request.ask.duration
|
||||||
check submitted.ask.size == request.ask.size
|
check submitted.ask.size == request.ask.size
|
||||||
|
@ -48,12 +43,12 @@ suite "Purchasing":
|
||||||
|
|
||||||
test "can change default value for proof probability":
|
test "can change default value for proof probability":
|
||||||
purchasing.proofProbability = 42.u256
|
purchasing.proofProbability = 42.u256
|
||||||
await purchaseAndWait(request)
|
discard purchasing.purchase(request)
|
||||||
check market.requested[0].ask.proofProbability == 42.u256
|
check market.requested[0].ask.proofProbability == 42.u256
|
||||||
|
|
||||||
test "can override proof probability per request":
|
test "can override proof probability per request":
|
||||||
request.ask.proofProbability = 42.u256
|
request.ask.proofProbability = 42.u256
|
||||||
await purchaseAndWait(request)
|
discard purchasing.purchase(request)
|
||||||
check market.requested[0].ask.proofProbability == 42.u256
|
check market.requested[0].ask.proofProbability == 42.u256
|
||||||
|
|
||||||
test "has a default value for request expiration interval":
|
test "has a default value for request expiration interval":
|
||||||
|
@ -62,66 +57,31 @@ suite "Purchasing":
|
||||||
test "can change default value for request expiration interval":
|
test "can change default value for request expiration interval":
|
||||||
purchasing.requestExpiryInterval = 42.u256
|
purchasing.requestExpiryInterval = 42.u256
|
||||||
let start = getTime().toUnix()
|
let start = getTime().toUnix()
|
||||||
await purchaseAndWait(request)
|
discard purchasing.purchase(request)
|
||||||
check market.requested[0].expiry == (start + 42).u256
|
check market.requested[0].expiry == (start + 42).u256
|
||||||
|
|
||||||
test "can override expiry time per request":
|
test "can override expiry time per request":
|
||||||
let expiry = (getTime().toUnix() + 42).u256
|
let expiry = (getTime().toUnix() + 42).u256
|
||||||
request.expiry = expiry
|
request.expiry = expiry
|
||||||
await purchaseAndWait(request)
|
discard purchasing.purchase(request)
|
||||||
check market.requested[0].expiry == expiry
|
check market.requested[0].expiry == expiry
|
||||||
|
|
||||||
test "includes a random nonce in every storage request":
|
test "includes a random nonce in every storage request":
|
||||||
await purchaseAndWait(request)
|
discard purchasing.purchase(request)
|
||||||
await purchaseAndWait(request)
|
discard purchasing.purchase(request)
|
||||||
check market.requested[0].nonce != market.requested[1].nonce
|
check market.requested[0].nonce != market.requested[1].nonce
|
||||||
|
|
||||||
proc createOffer(request: StorageRequest): StorageOffer =
|
test "succeeds when request is fulfilled":
|
||||||
StorageOffer(
|
|
||||||
requestId: request.id,
|
|
||||||
expiry: (getTime() + initDuration(hours = 1)).toUnix().u256
|
|
||||||
)
|
|
||||||
|
|
||||||
test "selects the cheapest offer":
|
|
||||||
let purchase = purchasing.purchase(request)
|
let purchase = purchasing.purchase(request)
|
||||||
let request = market.requested[0]
|
let request = market.requested[0]
|
||||||
var offer1, offer2 = createOffer(request)
|
let proof = seq[byte].example
|
||||||
offer1.price = 20.u256
|
await market.fulfillRequest(request.id, proof)
|
||||||
offer2.price = 10.u256
|
|
||||||
discard await market.offerStorage(offer1)
|
|
||||||
discard await market.offerStorage(offer2)
|
|
||||||
clock.set(request.expiry.truncate(int64))
|
|
||||||
await purchase.wait()
|
await purchase.wait()
|
||||||
check purchase.selected == some offer2
|
check purchase.error.isNone
|
||||||
check market.selected[0] == offer2.id
|
|
||||||
|
|
||||||
test "ignores offers that expired":
|
test "fails when request times out":
|
||||||
let expired = (getTime() - initTimeInterval(hours = 1)).toUnix().u256
|
|
||||||
let purchase = purchasing.purchase(request)
|
let purchase = purchasing.purchase(request)
|
||||||
let request = market.requested[0]
|
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))
|
clock.set(request.expiry.truncate(int64))
|
||||||
await purchase.wait()
|
expect PurchaseTimeout:
|
||||||
check market.selected[0] == offer1.id
|
await purchase.wait()
|
||||||
|
|
||||||
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
|
|
||||||
|
|
Loading…
Reference in New Issue