perf: contract storage optimizations (#1094)

* perf: contract storage optimizations

* Apply optimization changes

* Apply optimizing parameters sizing

* Update codex-contracts-eth

* bump latest changes in contracts branch

* Change requestDurationLimit to uint64

* fix tests

* fix tests

---------

Co-authored-by: Arnaud <arnaud@status.im>
Co-authored-by: Eric <5089238+emizzle@users.noreply.github.com>
This commit is contained in:
Adam Uhlíř 2025-02-20 08:11:06 +01:00 committed by GitHub
parent 04327a3986
commit 44981d24d0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
63 changed files with 585 additions and 567 deletions

View File

@ -40,5 +40,8 @@ proc toSecondsSince1970*(bytes: seq[byte]): SecondsSince1970 =
let asUint = uint64.fromBytes(bytes)
cast[int64](asUint)
proc toSecondsSince1970*(num: uint64): SecondsSince1970 =
cast[int64](num)
proc toSecondsSince1970*(bigint: UInt256): SecondsSince1970 =
bigint.truncate(int64)

View File

@ -11,7 +11,7 @@ type
collateral*: CollateralConfig
proofs*: ProofConfig
reservations*: SlotReservationsConfig
requestDurationLimit*: UInt256
requestDurationLimit*: uint64
CollateralConfig* = object
repairRewardPercentage*: uint8
@ -22,14 +22,14 @@ type
# percentage of the slashed amount going to the validators
ProofConfig* = object
period*: UInt256 # proofs requirements are calculated per period (in seconds)
timeout*: UInt256 # mark proofs as missing before the timeout (in seconds)
period*: uint64 # proofs requirements are calculated per period (in seconds)
timeout*: uint64 # mark proofs as missing before the timeout (in seconds)
downtime*: uint8 # ignore this much recent blocks for proof requirements
downtimeProduct*: uint8
zkeyHash*: string # hash of the zkey file which is linked to the verifier
# Ensures the pointer does not remain in downtime for many consecutive
# periods. For each period increase, move the pointer `pointerProduct`
# blocks. Should be a prime number to ensure there are no cycles.
downtimeProduct*: uint8
SlotReservationsConfig* = object
maxReservations*: uint8
@ -39,8 +39,8 @@ func fromTuple(_: type ProofConfig, tupl: tuple): ProofConfig =
period: tupl[0],
timeout: tupl[1],
downtime: tupl[2],
zkeyHash: tupl[3],
downtimeProduct: tupl[4],
downtimeProduct: tupl[3],
zkeyHash: tupl[4],
)
func fromTuple(_: type SlotReservationsConfig, tupl: tuple): SlotReservationsConfig =

View File

@ -84,7 +84,7 @@ method periodicity*(market: OnChainMarket): Future[Periodicity] {.async.} =
let period = config.proofs.period
return Periodicity(seconds: period)
method proofTimeout*(market: OnChainMarket): Future[UInt256] {.async.} =
method proofTimeout*(market: OnChainMarket): Future[uint64] {.async.} =
convertEthersError:
let config = await market.config()
return config.proofs.timeout
@ -94,7 +94,7 @@ method repairRewardPercentage*(market: OnChainMarket): Future[uint8] {.async.} =
let config = await market.config()
return config.collateral.repairRewardPercentage
method requestDurationLimit*(market: OnChainMarket): Future[UInt256] {.async.} =
method requestDurationLimit*(market: OnChainMarket): Future[uint64] {.async.} =
convertEthersError:
let config = await market.config()
return config.requestDurationLimit
@ -170,7 +170,7 @@ method requestExpiresAt*(
return await market.contract.requestExpiry(id)
method getHost(
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256
market: OnChainMarket, requestId: RequestId, slotIndex: uint64
): Future[?Address] {.async.} =
convertEthersError:
let slotId = slotId(requestId, slotIndex)
@ -196,7 +196,7 @@ method getActiveSlot*(market: OnChainMarket, slotId: SlotId): Future[?Slot] {.as
method fillSlot(
market: OnChainMarket,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
proof: Groth16Proof,
collateral: UInt256,
) {.async.} =
@ -280,7 +280,7 @@ method canProofBeMarkedAsMissing*(
return false
method reserveSlot*(
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256
market: OnChainMarket, requestId: RequestId, slotIndex: uint64
) {.async.} =
convertEthersError:
discard await market.contract
@ -293,7 +293,7 @@ method reserveSlot*(
.confirm(1)
method canReserveSlot*(
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256
market: OnChainMarket, requestId: RequestId, slotIndex: uint64
): Future[bool] {.async.} =
convertEthersError:
return await market.contract.canReserveSlot(requestId, slotIndex)
@ -329,10 +329,10 @@ method subscribeSlotFilled*(
method subscribeSlotFilled*(
market: OnChainMarket,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
callback: OnSlotFilled,
): Future[MarketSubscription] {.async.} =
proc onSlotFilled(eventRequestId: RequestId, eventSlotIndex: UInt256) =
proc onSlotFilled(eventRequestId: RequestId, eventSlotIndex: uint64) =
if eventRequestId == requestId and eventSlotIndex == slotIndex:
callback(requestId, slotIndex)

View File

@ -60,10 +60,6 @@ proc currentCollateral*(
marketplace: Marketplace, id: SlotId
): UInt256 {.contract, view.}
proc slashMisses*(marketplace: Marketplace): UInt256 {.contract, view.}
proc slashPercentage*(marketplace: Marketplace): UInt256 {.contract, view.}
proc minCollateralThreshold*(marketplace: Marketplace): UInt256 {.contract, view.}
proc requestStorage*(
marketplace: Marketplace, request: StorageRequest
): Confirmable {.
@ -76,10 +72,7 @@ proc requestStorage*(
.}
proc fillSlot*(
marketplace: Marketplace,
requestId: RequestId,
slotIndex: UInt256,
proof: Groth16Proof,
marketplace: Marketplace, requestId: RequestId, slotIndex: uint64, proof: Groth16Proof
): Confirmable {.
contract,
errors: [
@ -155,9 +148,6 @@ proc requestExpiry*(
marketplace: Marketplace, requestId: RequestId
): SecondsSince1970 {.contract, view.}
proc proofTimeout*(marketplace: Marketplace): UInt256 {.contract, view.}
proc proofEnd*(marketplace: Marketplace, id: SlotId): UInt256 {.contract, view.}
proc missingProofs*(marketplace: Marketplace, id: SlotId): UInt256 {.contract, view.}
proc isProofRequired*(marketplace: Marketplace, id: SlotId): bool {.contract, view.}
proc willProofBeRequired*(marketplace: Marketplace, id: SlotId): bool {.contract, view.}
@ -176,7 +166,7 @@ proc submitProof*(
.}
proc markProofAsMissing*(
marketplace: Marketplace, id: SlotId, period: UInt256
marketplace: Marketplace, id: SlotId, period: uint64
): Confirmable {.
contract,
errors: [
@ -187,9 +177,9 @@ proc markProofAsMissing*(
.}
proc reserveSlot*(
marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256
marketplace: Marketplace, requestId: RequestId, slotIndex: uint64
): Confirmable {.contract.}
proc canReserveSlot*(
marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256
marketplace: Marketplace, requestId: RequestId, slotIndex: uint64
): bool {.contract, view.}

View File

@ -9,6 +9,7 @@ import pkg/stew/byteutils
import pkg/libp2p/[cid, multicodec]
import ../logutils
import ../utils/json
import ../clock
from ../errors import mapFailure
export contractabi
@ -18,16 +19,16 @@ type
client* {.serialize.}: Address
ask* {.serialize.}: StorageAsk
content* {.serialize.}: StorageContent
expiry* {.serialize.}: UInt256
expiry* {.serialize.}: uint64
nonce*: Nonce
StorageAsk* = object
slots* {.serialize.}: uint64
slotSize* {.serialize.}: UInt256
duration* {.serialize.}: UInt256
proofProbability* {.serialize.}: UInt256
pricePerBytePerSecond* {.serialize.}: UInt256
collateralPerByte* {.serialize.}: UInt256
slots* {.serialize.}: uint64
slotSize* {.serialize.}: uint64
duration* {.serialize.}: uint64
maxSlotLoss* {.serialize.}: uint64
StorageContent* = object
@ -36,7 +37,7 @@ type
Slot* = object
request* {.serialize.}: StorageRequest
slotIndex* {.serialize.}: UInt256
slotIndex* {.serialize.}: uint64
SlotId* = distinct array[32, byte]
RequestId* = distinct array[32, byte]
@ -110,12 +111,12 @@ func fromTuple(_: type Slot, tupl: tuple): Slot =
func fromTuple(_: type StorageAsk, tupl: tuple): StorageAsk =
StorageAsk(
slots: tupl[0],
slotSize: tupl[1],
duration: tupl[2],
proofProbability: tupl[3],
pricePerBytePerSecond: tupl[4],
collateralPerByte: tupl[5],
proofProbability: tupl[0],
pricePerBytePerSecond: tupl[1],
collateralPerByte: tupl[2],
slots: tupl[3],
slotSize: tupl[4],
duration: tupl[5],
maxSlotLoss: tupl[6],
)
@ -177,21 +178,21 @@ func id*(request: StorageRequest): RequestId =
let encoding = AbiEncoder.encode((request,))
RequestId(keccak256.digest(encoding).data)
func slotId*(requestId: RequestId, slotIndex: UInt256): SlotId =
func slotId*(requestId: RequestId, slotIndex: uint64): SlotId =
let encoding = AbiEncoder.encode((requestId, slotIndex))
SlotId(keccak256.digest(encoding).data)
func slotId*(request: StorageRequest, slotIndex: UInt256): SlotId =
func slotId*(request: StorageRequest, slotIndex: uint64): SlotId =
slotId(request.id, slotIndex)
func id*(slot: Slot): SlotId =
slotId(slot.request, slot.slotIndex)
func pricePerSlotPerSecond*(ask: StorageAsk): UInt256 =
ask.pricePerBytePerSecond * ask.slotSize
ask.pricePerBytePerSecond * ask.slotSize.u256
func pricePerSlot*(ask: StorageAsk): UInt256 =
ask.duration * ask.pricePerSlotPerSecond
ask.duration.u256 * ask.pricePerSlotPerSecond
func totalPrice*(ask: StorageAsk): UInt256 =
ask.slots.u256 * ask.pricePerSlot
@ -200,7 +201,7 @@ func totalPrice*(request: StorageRequest): UInt256 =
request.ask.totalPrice
func collateralPerSlot*(ask: StorageAsk): UInt256 =
ask.collateralPerByte * ask.slotSize
ask.collateralPerByte * ask.slotSize.u256
func size*(ask: StorageAsk): UInt256 =
ask.slots.u256 * ask.slotSize
func size*(ask: StorageAsk): uint64 =
ask.slots * ask.slotSize

View File

@ -20,13 +20,12 @@ type
MarketError* = object of CodexError
Subscription* = ref object of RootObj
OnRequest* =
proc(id: RequestId, ask: StorageAsk, expiry: UInt256) {.gcsafe, upraises: [].}
proc(id: RequestId, ask: StorageAsk, expiry: uint64) {.gcsafe, upraises: [].}
OnFulfillment* = proc(requestId: RequestId) {.gcsafe, upraises: [].}
OnSlotFilled* =
proc(requestId: RequestId, slotIndex: UInt256) {.gcsafe, upraises: [].}
OnSlotFreed* = proc(requestId: RequestId, slotIndex: UInt256) {.gcsafe, upraises: [].}
OnSlotFilled* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
OnSlotFreed* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
OnSlotReservationsFull* =
proc(requestId: RequestId, slotIndex: UInt256) {.gcsafe, upraises: [].}
proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
OnRequestCancelled* = proc(requestId: RequestId) {.gcsafe, upraises: [].}
OnRequestFailed* = proc(requestId: RequestId) {.gcsafe, upraises: [].}
OnProofSubmitted* = proc(id: SlotId) {.gcsafe, upraises: [].}
@ -37,19 +36,19 @@ type
StorageRequested* = object of MarketplaceEvent
requestId*: RequestId
ask*: StorageAsk
expiry*: UInt256
expiry*: uint64
SlotFilled* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
slotIndex*: UInt256
slotIndex*: uint64
SlotFreed* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
slotIndex*: UInt256
slotIndex*: uint64
SlotReservationsFull* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
slotIndex*: UInt256
slotIndex*: uint64
RequestFulfilled* = object of MarketplaceEvent
requestId* {.indexed.}: RequestId
@ -72,13 +71,13 @@ method getSigner*(market: Market): Future[Address] {.base, async.} =
method periodicity*(market: Market): Future[Periodicity] {.base, async.} =
raiseAssert("not implemented")
method proofTimeout*(market: Market): Future[UInt256] {.base, async.} =
method proofTimeout*(market: Market): Future[uint64] {.base, async.} =
raiseAssert("not implemented")
method repairRewardPercentage*(market: Market): Future[uint8] {.base, async.} =
raiseAssert("not implemented")
method requestDurationLimit*(market: Market): Future[UInt256] {.base, async.} =
method requestDurationLimit*(market: Market): Future[uint64] {.base, async.} =
raiseAssert("not implemented")
method proofDowntime*(market: Market): Future[uint8] {.base, async.} =
@ -125,7 +124,7 @@ method requestExpiresAt*(
raiseAssert("not implemented")
method getHost*(
market: Market, requestId: RequestId, slotIndex: UInt256
market: Market, requestId: RequestId, slotIndex: uint64
): Future[?Address] {.base, async.} =
raiseAssert("not implemented")
@ -140,7 +139,7 @@ method getActiveSlot*(market: Market, slotId: SlotId): Future[?Slot] {.base, asy
method fillSlot*(
market: Market,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
proof: Groth16Proof,
collateral: UInt256,
) {.base, async.} =
@ -180,12 +179,12 @@ method canProofBeMarkedAsMissing*(
raiseAssert("not implemented")
method reserveSlot*(
market: Market, requestId: RequestId, slotIndex: UInt256
market: Market, requestId: RequestId, slotIndex: uint64
) {.base, async.} =
raiseAssert("not implemented")
method canReserveSlot*(
market: Market, requestId: RequestId, slotIndex: UInt256
market: Market, requestId: RequestId, slotIndex: uint64
): Future[bool] {.base, async.} =
raiseAssert("not implemented")
@ -205,7 +204,7 @@ method subscribeSlotFilled*(
raiseAssert("not implemented")
method subscribeSlotFilled*(
market: Market, requestId: RequestId, slotIndex: UInt256, callback: OnSlotFilled
market: Market, requestId: RequestId, slotIndex: uint64, callback: OnSlotFilled
): Future[Subscription] {.base, async.} =
raiseAssert("not implemented")

View File

@ -430,13 +430,13 @@ proc iterateManifests*(self: CodexNodeRef, onManifest: OnManifest) {.async.} =
proc setupRequest(
self: CodexNodeRef,
cid: Cid,
duration: UInt256,
duration: uint64,
proofProbability: UInt256,
nodes: uint,
tolerance: uint,
pricePerBytePerSecond: UInt256,
collateralPerByte: UInt256,
expiry: UInt256,
expiry: uint64,
): Future[?!StorageRequest] {.async.} =
## Setup slots for a given dataset
##
@ -494,7 +494,7 @@ proc setupRequest(
request = StorageRequest(
ask: StorageAsk(
slots: verifiable.numSlots.uint64,
slotSize: builder.slotBytes.uint.u256,
slotSize: builder.slotBytes.uint64,
duration: duration,
proofProbability: proofProbability,
pricePerBytePerSecond: pricePerBytePerSecond,
@ -511,13 +511,13 @@ proc setupRequest(
proc requestStorage*(
self: CodexNodeRef,
cid: Cid,
duration: UInt256,
duration: uint64,
proofProbability: UInt256,
nodes: uint,
tolerance: uint,
pricePerBytePerSecond: UInt256,
collateralPerByte: UInt256,
expiry: UInt256,
expiry: uint64,
): Future[?!PurchaseId] {.async.} =
## Initiate a request for storage sequence, this might
## be a multistep procedure.
@ -531,7 +531,7 @@ proc requestStorage*(
pricePerBytePerSecond = pricePerBytePerSecond
proofProbability = proofProbability
collateralPerByte = collateralPerByte
expiry = expiry.truncate(int64)
expiry = expiry
now = self.clock.now
trace "Received a request for storage!"
@ -553,7 +553,7 @@ proc requestStorage*(
success purchase.id
proc onStore(
self: CodexNodeRef, request: StorageRequest, slotIdx: UInt256, blocksCb: BlocksCb
self: CodexNodeRef, request: StorageRequest, slotIdx: uint64, blocksCb: BlocksCb
): Future[?!void] {.async.} =
## store data in local storage
##
@ -575,11 +575,9 @@ proc onStore(
trace "Unable to create slots builder", err = err.msg
return failure(err)
let
slotIdx = slotIdx.truncate(int)
expiry = request.expiry.toSecondsSince1970
let expiry = request.expiry
if slotIdx > manifest.slotRoots.high:
if slotIdx > manifest.slotRoots.high.uint64:
trace "Slot index not in manifest", slotIdx
return failure(newException(CodexError, "Slot index not in manifest"))
@ -587,7 +585,7 @@ proc onStore(
trace "Updating expiry for blocks", blocks = blocks.len
let ensureExpiryFutures =
blocks.mapIt(self.networkStore.ensureExpiry(it.cid, expiry))
blocks.mapIt(self.networkStore.ensureExpiry(it.cid, expiry.toSecondsSince1970))
if updateExpiryErr =? (await allFutureResult(ensureExpiryFutures)).errorOption:
return failure(updateExpiryErr)
@ -603,7 +601,11 @@ proc onStore(
trace "Unable to create indexing strategy from protected manifest", err = err.msg
return failure(err)
without blksIter =? indexer.getIndicies(slotIdx).catch, err:
if slotIdx > int.high.uint64:
error "Cannot cast slot index to int", slotIndex = slotIdx
return
without blksIter =? indexer.getIndicies(slotIdx.int).catch, err:
trace "Unable to get indicies from strategy", err = err.msg
return failure(err)
@ -613,13 +615,13 @@ proc onStore(
trace "Unable to fetch blocks", err = err.msg
return failure(err)
without slotRoot =? (await builder.buildSlot(slotIdx.Natural)), err:
without slotRoot =? (await builder.buildSlot(slotIdx.int)), err:
trace "Unable to build slot", err = err.msg
return failure(err)
trace "Slot successfully retrieved and reconstructed"
if cid =? slotRoot.toSlotCid() and cid != manifest.slotRoots[slotIdx.int]:
if cid =? slotRoot.toSlotCid() and cid != manifest.slotRoots[slotIdx]:
trace "Slot root mismatch",
manifest = manifest.slotRoots[slotIdx.int], recovered = slotRoot.toSlotCid()
return failure(newException(CodexError, "Slot root mismatch"))
@ -636,7 +638,7 @@ proc onProve(
let
cidStr = $slot.request.content.cid
slotIdx = slot.slotIndex.truncate(Natural)
slotIdx = slot.slotIndex
logScope:
cid = cidStr
@ -657,7 +659,8 @@ proc onProve(
return failure(err)
when defined(verify_circuit):
without (inputs, proof) =? await prover.prove(slotIdx, manifest, challenge), err:
without (inputs, proof) =? await prover.prove(slotIdx.int, manifest, challenge),
err:
error "Unable to generate proof", err = err.msg
return failure(err)
@ -671,7 +674,7 @@ proc onProve(
trace "Proof verified successfully"
else:
without (_, proof) =? await prover.prove(slotIdx, manifest, challenge), err:
without (_, proof) =? await prover.prove(slotIdx.int, manifest, challenge), err:
error "Unable to generate proof", err = err.msg
return failure(err)
@ -688,7 +691,7 @@ proc onExpiryUpdate(
): Future[?!void] {.async.} =
return await self.updateExpiry(rootCid, expiry)
proc onClear(self: CodexNodeRef, request: StorageRequest, slotIndex: UInt256) =
proc onClear(self: CodexNodeRef, request: StorageRequest, slotIndex: uint64) =
# TODO: remove data from local storage
discard
@ -704,7 +707,7 @@ proc start*(self: CodexNodeRef) {.async.} =
if hostContracts =? self.contracts.host:
hostContracts.sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] =
self.onStore(request, slot, onBatch)
@ -713,7 +716,7 @@ proc start*(self: CodexNodeRef) {.async.} =
): Future[?!void] =
self.onExpiryUpdate(rootCid, expiry)
hostContracts.sales.onClear = proc(request: StorageRequest, slotIndex: UInt256) =
hostContracts.sales.onClear = proc(request: StorageRequest, slotIndex: uint64) =
# TODO: remove data from local storage
self.onClear(request, slotIndex)

View File

@ -2,10 +2,10 @@ import pkg/stint
type
Periodicity* = object
seconds*: UInt256
seconds*: uint64
Period* = UInt256
Timestamp* = UInt256
Period* = uint64
Timestamp* = uint64
func periodOf*(periodicity: Periodicity, timestamp: Timestamp): Period =
timestamp div periodicity.seconds

View File

@ -463,7 +463,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
Http400, "Total size must be larger then zero", headers = headers
)
if not reservations.hasAvailable(restAv.totalSize.truncate(uint)):
if not reservations.hasAvailable(restAv.totalSize):
return
RestApiResponse.error(Http422, "Not enough storage quota", headers = headers)

View File

@ -13,11 +13,11 @@ export json
type
StorageRequestParams* = object
duration* {.serialize.}: UInt256
duration* {.serialize.}: uint64
proofProbability* {.serialize.}: UInt256
pricePerBytePerSecond* {.serialize.}: UInt256
collateralPerByte* {.serialize.}: UInt256
expiry* {.serialize.}: ?UInt256
expiry* {.serialize.}: ?uint64
nodes* {.serialize.}: ?uint
tolerance* {.serialize.}: ?uint
@ -28,16 +28,16 @@ type
error* {.serialize.}: ?string
RestAvailability* = object
totalSize* {.serialize.}: UInt256
duration* {.serialize.}: UInt256
totalSize* {.serialize.}: uint64
duration* {.serialize.}: uint64
minPricePerBytePerSecond* {.serialize.}: UInt256
totalCollateral* {.serialize.}: UInt256
freeSize* {.serialize.}: ?UInt256
freeSize* {.serialize.}: ?uint64
RestSalesAgent* = object
state* {.serialize.}: string
requestId* {.serialize.}: RequestId
slotIndex* {.serialize.}: UInt256
slotIndex* {.serialize.}: uint64
request* {.serialize.}: ?StorageRequest
reservation* {.serialize.}: ?Reservation

View File

@ -150,16 +150,16 @@ proc cleanUp(
).errorOption:
error "failure deleting reservation", error = deleteErr.msg
if data.slotIndex > uint16.high.uint64:
error "Cannot cast slot index to uint16", slotIndex = data.slotIndex
return
# Re-add items back into the queue to prevent small availabilities from
# draining the queue. Seen items will be ordered last.
if reprocessSlot and request =? data.request:
let queue = sales.context.slotQueue
var seenItem = SlotQueueItem.init(
data.requestId,
data.slotIndex.truncate(uint16),
data.ask,
request.expiry,
seen = true,
data.requestId, data.slotIndex.uint16, data.ask, request.expiry, seen = true
)
trace "pushing ignored item to queue, marked as seen"
if err =? queue.push(seenItem).errorOption:
@ -172,7 +172,7 @@ proc cleanUp(
processing.complete()
proc filled(
sales: Sales, request: StorageRequest, slotIndex: UInt256, processing: Future[void]
sales: Sales, request: StorageRequest, slotIndex: uint64, processing: Future[void]
) =
if onSale =? sales.context.onSale:
onSale(request, slotIndex)
@ -184,16 +184,15 @@ proc filled(
proc processSlot(sales: Sales, item: SlotQueueItem, done: Future[void]) =
debug "Processing slot from queue", requestId = item.requestId, slot = item.slotIndex
let agent = newSalesAgent(
sales.context, item.requestId, item.slotIndex.u256, none StorageRequest
)
let agent =
newSalesAgent(sales.context, item.requestId, item.slotIndex, none StorageRequest)
agent.onCleanUp = proc(
returnBytes = false, reprocessSlot = false, returnedCollateral = UInt256.none
) {.async.} =
await sales.cleanUp(agent, returnBytes, reprocessSlot, returnedCollateral, done)
agent.onFilled = some proc(request: StorageRequest, slotIndex: UInt256) =
agent.onFilled = some proc(request: StorageRequest, slotIndex: uint64) =
sales.filled(request, slotIndex, done)
agent.start(SalePreparing())
@ -283,7 +282,7 @@ proc onAvailabilityAdded(sales: Sales, availability: Availability) {.async.} =
queue.unpause()
proc onStorageRequested(
sales: Sales, requestId: RequestId, ask: StorageAsk, expiry: UInt256
sales: Sales, requestId: RequestId, ask: StorageAsk, expiry: uint64
) =
logScope:
topics = "marketplace sales onStorageRequested"
@ -312,7 +311,7 @@ proc onStorageRequested(
else:
warn "Error adding request to SlotQueue", error = err.msg
proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: UInt256) =
proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: uint64) =
logScope:
topics = "marketplace sales onSlotFreed"
requestId
@ -325,8 +324,12 @@ proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: UInt256) =
let market = context.market
let queue = context.slotQueue
# first attempt to populate request using existing slot metadata in queue
without var found =? queue.populateItem(requestId, slotIndex.truncate(uint16)):
if slotIndex > uint16.high.uint64:
error "Cannot cast slot index to uint16, value = ", slotIndex
return
# first attempt to populate request using existing metadata in queue
without var found =? queue.populateItem(requestId, slotIndex.uint16):
trace "no existing request metadata, getting request info from contract"
# if there's no existing slot for that request, retrieve the request
# from the contract.
@ -335,7 +338,7 @@ proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: UInt256) =
error "unknown request in contract"
return
found = SlotQueueItem.init(request, slotIndex.truncate(uint16))
found = SlotQueueItem.init(request, slotIndex.uint16)
except CancelledError:
discard # do not propagate as addSlotToQueue was asyncSpawned
except CatchableError as e:
@ -353,7 +356,7 @@ proc subscribeRequested(sales: Sales) {.async.} =
let context = sales.context
let market = context.market
proc onStorageRequested(requestId: RequestId, ask: StorageAsk, expiry: UInt256) =
proc onStorageRequested(requestId: RequestId, ask: StorageAsk, expiry: uint64) =
sales.onStorageRequested(requestId, ask, expiry)
try:
@ -426,9 +429,13 @@ proc subscribeSlotFilled(sales: Sales) {.async.} =
let market = context.market
let queue = context.slotQueue
proc onSlotFilled(requestId: RequestId, slotIndex: UInt256) =
proc onSlotFilled(requestId: RequestId, slotIndex: uint64) =
if slotIndex > uint16.high.uint64:
error "Cannot cast slot index to uint16, value = ", slotIndex
return
trace "slot filled, removing from slot queue", requestId, slotIndex
queue.delete(requestId, slotIndex.truncate(uint16))
queue.delete(requestId, slotIndex.uint16)
for agent in sales.agents:
agent.onSlotFilled(requestId, slotIndex)
@ -445,7 +452,7 @@ proc subscribeSlotFreed(sales: Sales) {.async.} =
let context = sales.context
let market = context.market
proc onSlotFreed(requestId: RequestId, slotIndex: UInt256) =
proc onSlotFreed(requestId: RequestId, slotIndex: uint64) =
sales.onSlotFreed(requestId, slotIndex)
try:
@ -461,9 +468,13 @@ proc subscribeSlotReservationsFull(sales: Sales) {.async.} =
let market = context.market
let queue = context.slotQueue
proc onSlotReservationsFull(requestId: RequestId, slotIndex: UInt256) =
proc onSlotReservationsFull(requestId: RequestId, slotIndex: uint64) =
if slotIndex > uint16.high.uint64:
error "Cannot cast slot index to uint16, value = ", slotIndex
return
trace "reservations for slot full, removing from slot queue", requestId, slotIndex
queue.delete(requestId, slotIndex.truncate(uint16))
queue.delete(requestId, slotIndex.uint16)
try:
let sub = await market.subscribeSlotReservationsFull(onSlotReservationsFull)

View File

@ -64,9 +64,9 @@ type
SomeStorableId = AvailabilityId | ReservationId
Availability* = ref object
id* {.serialize.}: AvailabilityId
totalSize* {.serialize.}: UInt256
freeSize* {.serialize.}: UInt256
duration* {.serialize.}: UInt256
totalSize* {.serialize.}: uint64
freeSize* {.serialize.}: uint64
duration* {.serialize.}: uint64
minPricePerBytePerSecond* {.serialize.}: UInt256
totalCollateral {.serialize.}: UInt256
totalRemainingCollateral* {.serialize.}: UInt256
@ -74,9 +74,9 @@ type
Reservation* = ref object
id* {.serialize.}: ReservationId
availabilityId* {.serialize.}: AvailabilityId
size* {.serialize.}: UInt256
size* {.serialize.}: uint64
requestId* {.serialize.}: RequestId
slotIndex* {.serialize.}: UInt256
slotIndex* {.serialize.}: uint64
Reservations* = ref object of RootObj
availabilityLock: AsyncLock
@ -123,9 +123,9 @@ proc new*(T: type Reservations, repo: RepoStore): Reservations =
proc init*(
_: type Availability,
totalSize: UInt256,
freeSize: UInt256,
duration: UInt256,
totalSize: uint64,
freeSize: uint64,
duration: uint64,
minPricePerBytePerSecond: UInt256,
totalCollateral: UInt256,
): Availability =
@ -151,9 +151,9 @@ proc `totalCollateral=`*(self: Availability, value: UInt256) {.inline.} =
proc init*(
_: type Reservation,
availabilityId: AvailabilityId,
size: UInt256,
size: uint64,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
): Reservation =
var id: array[32, byte]
doAssert randomBytes(id) == 32
@ -206,7 +206,7 @@ func key*(availability: Availability): ?!Key =
return availability.id.key
func maxCollateralPerByte*(availability: Availability): UInt256 =
return availability.totalRemainingCollateral div availability.freeSize
return availability.totalRemainingCollateral div availability.freeSize.stuint(256)
func key*(reservation: Reservation): ?!Key =
return key(reservation.id, reservation.availabilityId)
@ -289,16 +289,12 @@ proc updateAvailability(
trace "totalSize changed, updating repo reservation"
if oldAvailability.totalSize < obj.totalSize: # storage added
if reserveErr =? (
await self.repo.reserve(
(obj.totalSize - oldAvailability.totalSize).truncate(uint).NBytes
)
await self.repo.reserve((obj.totalSize - oldAvailability.totalSize).NBytes)
).errorOption:
return failure(reserveErr.toErr(ReserveFailedError))
elif oldAvailability.totalSize > obj.totalSize: # storage removed
if reserveErr =? (
await self.repo.release(
(oldAvailability.totalSize - obj.totalSize).truncate(uint).NBytes
)
await self.repo.release((oldAvailability.totalSize - obj.totalSize).NBytes)
).errorOption:
return failure(reserveErr.toErr(ReleaseFailedError))
@ -361,7 +357,7 @@ proc deleteReservation*(
else:
return failure(error)
if reservation.size > 0.u256:
if reservation.size > 0.uint64:
trace "returning remaining reservation bytes to availability",
size = reservation.size
@ -389,8 +385,8 @@ proc deleteReservation*(
proc createAvailability*(
self: Reservations,
size: UInt256,
duration: UInt256,
size: uint64,
duration: uint64,
minPricePerBytePerSecond: UInt256,
totalCollateral: UInt256,
): Future[?!Availability] {.async.} =
@ -399,7 +395,7 @@ proc createAvailability*(
let availability =
Availability.init(size, size, duration, minPricePerBytePerSecond, totalCollateral)
let bytes = availability.freeSize.truncate(uint)
let bytes = availability.freeSize
if reserveErr =? (await self.repo.reserve(bytes.NBytes)).errorOption:
return failure(reserveErr.toErr(ReserveFailedError))
@ -418,9 +414,9 @@ proc createAvailability*(
method createReservation*(
self: Reservations,
availabilityId: AvailabilityId,
slotSize: UInt256,
slotSize: uint64,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
collateralPerByte: UInt256,
): Future[?!Reservation] {.async, base.} =
withLock(self.availabilityLock):
@ -450,7 +446,7 @@ method createReservation*(
availability.freeSize -= slotSize
# adjust the remaining totalRemainingCollateral
availability.totalRemainingCollateral -= slotSize * collateralPerByte
availability.totalRemainingCollateral -= slotSize.stuint(256) * collateralPerByte
# update availability with reduced size
trace "Updating availability with reduced size"
@ -475,7 +471,7 @@ proc returnBytesToAvailability*(
self: Reservations,
availabilityId: AvailabilityId,
reservationId: ReservationId,
bytes: UInt256,
bytes: uint64,
): Future[?!void] {.async.} =
logScope:
reservationId
@ -502,8 +498,7 @@ proc returnBytesToAvailability*(
# First lets see if we can re-reserve the bytes, if the Repo's quota
# is depleted then we will fail-fast as there is nothing to be done atm.
if reserveErr =?
(await self.repo.reserve(bytesToBeReturned.truncate(uint).NBytes)).errorOption:
if reserveErr =? (await self.repo.reserve(bytesToBeReturned.NBytes)).errorOption:
return failure(reserveErr.toErr(ReserveFailedError))
without availabilityKey =? availabilityId.key, error:
@ -517,8 +512,7 @@ proc returnBytesToAvailability*(
# Update availability with returned size
if updateErr =? (await self.updateAvailability(availability)).errorOption:
trace "Rolling back returning bytes"
if rollbackErr =?
(await self.repo.release(bytesToBeReturned.truncate(uint).NBytes)).errorOption:
if rollbackErr =? (await self.repo.release(bytesToBeReturned.NBytes)).errorOption:
rollbackErr.parent = updateErr
return failure(rollbackErr)
@ -546,7 +540,7 @@ proc release*(
without var reservation =? (await self.get(key, Reservation)), error:
return failure(error)
if reservation.size < bytes.u256:
if reservation.size < bytes:
let error = newException(
BytesOutOfBoundsError,
"trying to release an amount of bytes that is greater than the total size of the Reservation",
@ -556,7 +550,7 @@ proc release*(
if releaseErr =? (await self.repo.release(bytes.NBytes)).errorOption:
return failure(releaseErr.toErr(ReleaseFailedError))
reservation.size -= bytes.u256
reservation.size -= bytes
# persist partially used Reservation with updated size
if err =? (await self.update(reservation)).errorOption:
@ -643,7 +637,8 @@ proc all*(
proc findAvailability*(
self: Reservations,
size, duration, pricePerBytePerSecond, collateralPerByte: UInt256,
size, duration: uint64,
pricePerBytePerSecond, collateralPerByte: UInt256,
): Future[?Availability] {.async.} =
without storables =? (await self.storables(Availability)), e:
error "failed to get all storables", error = e.msg

View File

@ -29,7 +29,7 @@ type
OnCleanUp* = proc(
returnBytes = false, reprocessSlot = false, returnedCollateral = UInt256.none
): Future[void] {.gcsafe, upraises: [].}
OnFilled* = proc(request: StorageRequest, slotIndex: UInt256) {.gcsafe, upraises: [].}
OnFilled* = proc(request: StorageRequest, slotIndex: uint64) {.gcsafe, upraises: [].}
SalesAgentError = object of CodexError
AllSlotsFilledError* = object of SalesAgentError
@ -40,7 +40,7 @@ func `==`*(a, b: SalesAgent): bool =
proc newSalesAgent*(
context: SalesContext,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
request: ?StorageRequest,
): SalesAgent =
var agent = SalesAgent.new()
@ -121,7 +121,7 @@ method onFailed*(
agent.schedule(failedEvent(request))
method onSlotFilled*(
agent: SalesAgent, requestId: RequestId, slotIndex: UInt256
agent: SalesAgent, requestId: RequestId, slotIndex: uint64
) {.base, gcsafe, upraises: [].} =
if agent.data.requestId == requestId and agent.data.slotIndex == slotIndex:
agent.schedule(slotFilledEvent(requestId, slotIndex))

View File

@ -26,7 +26,7 @@ type
BlocksCb* = proc(blocks: seq[bt.Block]): Future[?!void] {.gcsafe, raises: [].}
OnStore* = proc(
request: StorageRequest, slot: UInt256, blocksCb: BlocksCb
request: StorageRequest, slot: uint64, blocksCb: BlocksCb
): Future[?!void] {.gcsafe, upraises: [].}
OnProve* = proc(slot: Slot, challenge: ProofChallenge): Future[?!Groth16Proof] {.
gcsafe, upraises: []
@ -34,5 +34,5 @@ type
OnExpiryUpdate* = proc(rootCid: Cid, expiry: SecondsSince1970): Future[?!void] {.
gcsafe, upraises: []
.}
OnClear* = proc(request: StorageRequest, slotIndex: UInt256) {.gcsafe, upraises: [].}
OnSale* = proc(request: StorageRequest, slotIndex: UInt256) {.gcsafe, upraises: [].}
OnClear* = proc(request: StorageRequest, slotIndex: uint64) {.gcsafe, upraises: [].}
OnSale* = proc(request: StorageRequest, slotIndex: uint64) {.gcsafe, upraises: [].}

View File

@ -7,6 +7,6 @@ type SalesData* = ref object
requestId*: RequestId
ask*: StorageAsk
request*: ?StorageRequest
slotIndex*: UInt256
slotIndex*: uint64
cancelled*: Future[void]
reservation*: ?Reservation

View File

@ -5,6 +5,7 @@ import pkg/questionable
import pkg/questionable/results
import pkg/upraises
import ../errors
import ../clock
import ../logutils
import ../rng
import ../utils
@ -30,11 +31,11 @@ type
SlotQueueItem* = object
requestId: RequestId
slotIndex: uint16
slotSize: UInt256
duration: UInt256
slotSize: uint64
duration: uint64
pricePerBytePerSecond: UInt256
collateralPerByte: UInt256
expiry: UInt256
expiry: uint64
seen: bool
# don't need to -1 to prevent overflow when adding 1 (to always allow push)
@ -135,7 +136,7 @@ proc init*(
requestId: RequestId,
slotIndex: uint16,
ask: StorageAsk,
expiry: UInt256,
expiry: uint64,
seen = false,
): SlotQueueItem =
SlotQueueItem(
@ -155,7 +156,7 @@ proc init*(
SlotQueueItem.init(request.id, slotIndex, request.ask, request.expiry)
proc init*(
_: type SlotQueueItem, requestId: RequestId, ask: StorageAsk, expiry: UInt256
_: type SlotQueueItem, requestId: RequestId, ask: StorageAsk, expiry: uint64
): seq[SlotQueueItem] =
if not ask.slots.inRange:
raise newException(SlotsOutOfRangeError, "Too many slots")
@ -182,10 +183,10 @@ proc requestId*(self: SlotQueueItem): RequestId =
proc slotIndex*(self: SlotQueueItem): uint16 =
self.slotIndex
proc slotSize*(self: SlotQueueItem): UInt256 =
proc slotSize*(self: SlotQueueItem): uint64 =
self.slotSize
proc duration*(self: SlotQueueItem): UInt256 =
proc duration*(self: SlotQueueItem): uint64 =
self.duration
proc pricePerBytePerSecond*(self: SlotQueueItem): UInt256 =

View File

@ -25,7 +25,7 @@ method onFailed*(
discard
method onSlotFilled*(
state: SaleState, requestId: RequestId, slotIndex: UInt256
state: SaleState, requestId: RequestId, slotIndex: uint64
): ?State {.base, upraises: [].} =
discard
@ -37,6 +37,6 @@ proc failedEvent*(request: StorageRequest): Event =
return proc(state: State): ?State =
SaleState(state).onFailed(request)
proc slotFilledEvent*(requestId: RequestId, slotIndex: UInt256): Event =
proc slotFilledEvent*(requestId: RequestId, slotIndex: uint64): Event =
return proc(state: State): ?State =
SaleState(state).onSlotFilled(requestId, slotIndex)

View File

@ -28,7 +28,7 @@ method onFailed*(state: SaleDownloading, request: StorageRequest): ?State =
return some State(SaleFailed())
method onSlotFilled*(
state: SaleDownloading, requestId: RequestId, slotIndex: UInt256
state: SaleDownloading, requestId: RequestId, slotIndex: uint64
): ?State =
return some State(SaleFilled())

View File

@ -25,9 +25,9 @@ method onFailed*(state: SaleInitialProving, request: StorageRequest): ?State =
proc waitUntilNextPeriod(clock: Clock, periodicity: Periodicity) {.async.} =
trace "Waiting until next period"
let period = periodicity.periodOf(clock.now().u256)
let periodEnd = periodicity.periodEnd(period).truncate(int64)
await clock.waitUntil(periodEnd + 1)
let period = periodicity.periodOf(clock.now().Timestamp)
let periodEnd = periodicity.periodEnd(period)
await clock.waitUntil((periodEnd + 1).toSecondsSince1970)
proc waitForStableChallenge(market: Market, clock: Clock, slotId: SlotId) {.async.} =
let periodicity = await market.periodicity()

View File

@ -33,7 +33,7 @@ method onFailed*(state: SalePreparing, request: StorageRequest): ?State =
return some State(SaleFailed())
method onSlotFilled*(
state: SalePreparing, requestId: RequestId, slotIndex: UInt256
state: SalePreparing, requestId: RequestId, slotIndex: uint64
): ?State =
return some State(SaleFilled())

View File

@ -46,7 +46,7 @@ proc proveLoop(
market: Market,
clock: Clock,
request: StorageRequest,
slotIndex: UInt256,
slotIndex: uint64,
onProve: OnProve,
) {.async.} =
let slot = Slot(request: request, slotIndex: slotIndex)
@ -60,12 +60,12 @@ proc proveLoop(
proc getCurrentPeriod(): Future[Period] {.async.} =
let periodicity = await market.periodicity()
return periodicity.periodOf(clock.now().u256)
return periodicity.periodOf(clock.now().Timestamp)
proc waitUntilPeriod(period: Period) {.async.} =
let periodicity = await market.periodicity()
# Ensure that we're past the period boundary by waiting an additional second
await clock.waitUntil(periodicity.periodStart(period).truncate(int64) + 1)
await clock.waitUntil((periodicity.periodStart(period) + 1).toSecondsSince1970)
while true:
let currentPeriod = await getCurrentPeriod()

View File

@ -20,7 +20,7 @@ when codex_enable_proof_failures:
failEveryNProofs*: int
proofCount: int
proc onSubmitProofError(error: ref CatchableError, period: UInt256, slotId: SlotId) =
proc onSubmitProofError(error: ref CatchableError, period: Period, slotId: SlotId) =
error "Submitting invalid proof failed", period, slotId, msg = error.msgDetail
method prove*(

View File

@ -2,6 +2,7 @@ import std/sets
import std/sequtils
import pkg/chronos
import pkg/questionable/results
import pkg/stew/endians2
import ./validationconfig
import ./market
@ -19,7 +20,7 @@ type Validation* = ref object
subscriptions: seq[Subscription]
running: Future[void]
periodicity: Periodicity
proofTimeout: UInt256
proofTimeout: uint64
config: ValidationConfig
logScope:
@ -33,18 +34,19 @@ proc new*(
proc slots*(validation: Validation): seq[SlotId] =
validation.slots.toSeq
proc getCurrentPeriod(validation: Validation): UInt256 =
return validation.periodicity.periodOf(validation.clock.now().u256)
proc getCurrentPeriod(validation: Validation): Period =
return validation.periodicity.periodOf(validation.clock.now().Timestamp)
proc waitUntilNextPeriod(validation: Validation) {.async.} =
let period = validation.getCurrentPeriod()
let periodEnd = validation.periodicity.periodEnd(period)
trace "Waiting until next period", currentPeriod = period
await validation.clock.waitUntil(periodEnd.truncate(int64) + 1)
await validation.clock.waitUntil((periodEnd + 1).toSecondsSince1970)
func groupIndexForSlotId*(slotId: SlotId, validationGroups: ValidationGroups): uint16 =
let slotIdUInt256 = UInt256.fromBytesBE(slotId.toArray)
(slotIdUInt256 mod validationGroups.u256).truncate(uint16)
let a = slotId.toArray
let slotIdInt64 = uint64.fromBytesBE(a)
(slotIdInt64 mod uint64(validationGroups)).uint16
func maxSlotsConstraintRespected(validation: Validation): bool =
validation.config.maxSlots == 0 or validation.slots.len < validation.config.maxSlots
@ -55,7 +57,7 @@ func shouldValidateSlot(validation: Validation, slotId: SlotId): bool =
groupIndexForSlotId(slotId, validationGroups) == validation.config.groupIndex
proc subscribeSlotFilled(validation: Validation) {.async.} =
proc onSlotFilled(requestId: RequestId, slotIndex: UInt256) =
proc onSlotFilled(requestId: RequestId, slotIndex: uint64) =
if not validation.maxSlotsConstraintRespected:
return
let slotId = slotId(requestId, slotIndex)
@ -113,17 +115,13 @@ proc run(validation: Validation) {.async: (raises: []).} =
except CatchableError as e:
error "Validation failed", msg = e.msg
proc epochForDurationBackFromNow(
validation: Validation, duration: Duration
): SecondsSince1970 =
return validation.clock.now - duration.secs
proc findEpoch(validation: Validation, secondsAgo: uint64): SecondsSince1970 =
return validation.clock.now - secondsAgo.int64
proc restoreHistoricalState(validation: Validation) {.async.} =
trace "Restoring historical state..."
let requestDurationLimit = await validation.market.requestDurationLimit
let startTimeEpoch = validation.epochForDurationBackFromNow(
seconds(requestDurationLimit.truncate(int64))
)
let startTimeEpoch = validation.findEpoch(secondsAgo = requestDurationLimit)
let slotFilledEvents =
await validation.market.queryPastSlotFilledEvents(fromTime = startTimeEpoch)
for event in slotFilledEvents:

View File

@ -68,19 +68,19 @@ proc example*(_: type MultiHash, mcodec = Sha256HashCodec): MultiHash =
proc example*(
_: type Availability, collateralPerByte = uint8.example.u256
): Availability =
let totalSize = uint16.example.u256
let totalSize = uint16.example.uint64
Availability.init(
totalSize = totalSize,
freeSize = uint16.example.u256,
duration = uint16.example.u256,
freeSize = uint16.example.uint64,
duration = uint16.example.uint64,
minPricePerBytePerSecond = uint8.example.u256,
totalCollateral = totalSize * collateralPerByte,
totalCollateral = totalSize.u256 * collateralPerByte,
)
proc example*(_: type Reservation): Reservation =
Reservation.init(
availabilityId = AvailabilityId(array[32, byte].example),
size = uint16.example.u256,
size = uint16.example.uint64,
slotId = SlotId.example,
)

View File

@ -57,7 +57,7 @@ type
MockSlot* = object
requestId*: RequestId
host*: Address
slotIndex*: UInt256
slotIndex*: uint64
proof*: Groth16Proof
timestamp: ?SecondsSince1970
collateral*: UInt256
@ -84,7 +84,7 @@ type
SlotFilledSubscription* = ref object of Subscription
market: MockMarket
requestId: ?RequestId
slotIndex: ?UInt256
slotIndex: ?uint64
callback: OnSlotFilled
SlotFreedSubscription* = ref object of Subscription
@ -126,10 +126,13 @@ proc new*(_: type MockMarket, clock: ?Clock = Clock.none): MockMarket =
validatorRewardPercentage: 20,
),
proofs: ProofConfig(
period: 10.u256, timeout: 5.u256, downtime: 64.uint8, downtimeProduct: 67.uint8
period: 10.Period,
timeout: 5.uint64,
downtime: 64.uint8,
downtimeProduct: 67.uint8,
),
reservations: SlotReservationsConfig(maxReservations: 3),
requestDurationLimit: (60 * 60 * 24 * 30).u256,
requestDurationLimit: (60 * 60 * 24 * 30).uint64,
)
MockMarket(
signer: Address.example, config: config, canReserveSlot: true, clock: clock
@ -141,10 +144,10 @@ method getSigner*(market: MockMarket): Future[Address] {.async.} =
method periodicity*(mock: MockMarket): Future[Periodicity] {.async.} =
return Periodicity(seconds: mock.config.proofs.period)
method proofTimeout*(market: MockMarket): Future[UInt256] {.async.} =
method proofTimeout*(market: MockMarket): Future[uint64] {.async.} =
return market.config.proofs.timeout
method requestDurationLimit*(market: MockMarket): Future[UInt256] {.async.} =
method requestDurationLimit*(market: MockMarket): Future[uint64] {.async.} =
return market.config.requestDurationLimit
method proofDowntime*(market: MockMarket): Future[uint8] {.async.} =
@ -176,9 +179,9 @@ method getRequest*(
return some request
return none StorageRequest
method getActiveSlot*(market: MockMarket, slotId: SlotId): Future[?Slot] {.async.} =
method getActiveSlot*(market: MockMarket, id: SlotId): Future[?Slot] {.async.} =
for slot in market.filled:
if slotId(slot.requestId, slot.slotIndex) == slotId and
if slotId(slot.requestId, slot.slotIndex) == id and
request =? await market.getRequest(slot.requestId):
return some Slot(request: request, slotIndex: slot.slotIndex)
return none Slot
@ -204,7 +207,7 @@ method requestExpiresAt*(
return market.requestExpiry[id]
method getHost*(
market: MockMarket, requestId: RequestId, slotIndex: UInt256
market: MockMarket, requestId: RequestId, slotIndex: uint64
): Future[?Address] {.async.} =
for slot in market.filled:
if slot.requestId == requestId and slot.slotIndex == slotIndex:
@ -219,7 +222,7 @@ method currentCollateral*(
return slot.collateral
return 0.u256
proc emitSlotFilled*(market: MockMarket, requestId: RequestId, slotIndex: UInt256) =
proc emitSlotFilled*(market: MockMarket, requestId: RequestId, slotIndex: uint64) =
var subscriptions = market.subscriptions.onSlotFilled
for subscription in subscriptions:
let requestMatches =
@ -229,13 +232,13 @@ proc emitSlotFilled*(market: MockMarket, requestId: RequestId, slotIndex: UInt25
if requestMatches and slotMatches:
subscription.callback(requestId, slotIndex)
proc emitSlotFreed*(market: MockMarket, requestId: RequestId, slotIndex: UInt256) =
proc emitSlotFreed*(market: MockMarket, requestId: RequestId, slotIndex: uint64) =
var subscriptions = market.subscriptions.onSlotFreed
for subscription in subscriptions:
subscription.callback(requestId, slotIndex)
proc emitSlotReservationsFull*(
market: MockMarket, requestId: RequestId, slotIndex: UInt256
market: MockMarket, requestId: RequestId, slotIndex: uint64
) =
var subscriptions = market.subscriptions.onSlotReservationsFull
for subscription in subscriptions:
@ -262,7 +265,7 @@ proc emitRequestFailed*(market: MockMarket, requestId: RequestId) =
proc fillSlot*(
market: MockMarket,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
proof: Groth16Proof,
host: Address,
collateral = 0.u256,
@ -282,7 +285,7 @@ proc fillSlot*(
method fillSlot*(
market: MockMarket,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
proof: Groth16Proof,
collateral: UInt256,
) {.async.} =
@ -346,13 +349,13 @@ method canProofBeMarkedAsMissing*(
return market.canBeMarkedAsMissing.contains(id)
method reserveSlot*(
market: MockMarket, requestId: RequestId, slotIndex: UInt256
market: MockMarket, requestId: RequestId, slotIndex: uint64
) {.async.} =
if error =? market.reserveSlotThrowError:
raise error
method canReserveSlot*(
market: MockMarket, requestId: RequestId, slotIndex: UInt256
market: MockMarket, requestId: RequestId, slotIndex: uint64
): Future[bool] {.async.} =
return market.canReserveSlot
@ -395,7 +398,7 @@ method subscribeSlotFilled*(
return subscription
method subscribeSlotFilled*(
market: MockMarket, requestId: RequestId, slotIndex: UInt256, callback: OnSlotFilled
market: MockMarket, requestId: RequestId, slotIndex: uint64, callback: OnSlotFilled
): Future[Subscription] {.async.} =
let subscription = SlotFilledSubscription(
market: market,

View File

@ -24,9 +24,9 @@ proc setCreateReservationThrowError*(
method createReservation*(
self: MockReservations,
availabilityId: AvailabilityId,
slotSize: UInt256,
slotSize: uint64,
requestId: RequestId,
slotIndex: UInt256,
slotIndex: uint64,
collateralPerByte: UInt256,
): Future[?!Reservation] {.async.} =
if self.createReservationThrowBytesOutOfBoundsError:

View File

@ -12,6 +12,6 @@ method onFailed*(agent: SalesAgent, requestId: RequestId) =
failedCalled = true
method onSlotFilled*(
agent: SalesAgent, requestId: RequestId, slotIndex: UInt256
agent: SalesAgent, requestId: RequestId, slotIndex: uint64
) {.base.} =
slotFilledCalled = true

View File

@ -4,11 +4,11 @@ import pkg/codex/sales/slotqueue
type MockSlotQueueItem* = object
requestId*: RequestId
slotIndex*: uint16
slotSize*: UInt256
duration*: UInt256
slotSize*: uint64
duration*: uint64
pricePerBytePerSecond*: UInt256
collateralPerByte*: UInt256
expiry*: UInt256
expiry*: uint64
seen*: bool
proc toSlotQueueItem*(item: MockSlotQueueItem): SlotQueueItem =

View File

@ -116,7 +116,8 @@ asyncchecksuite "Test Node - Host contracts":
let onStore = !sales.onStore
var request = StorageRequest.example
request.content.cid = verifiableBlock.cid
request.expiry = (getTime() + DefaultBlockTtl.toTimesDuration + 1.hours).toUnix.u256
request.expiry =
(getTime() + DefaultBlockTtl.toTimesDuration + 1.hours).toUnix.uint64
var fetchedBytes: uint = 0
let onBlocks = proc(blocks: seq[bt.Block]): Future[?!void] {.async.} =
@ -124,7 +125,7 @@ asyncchecksuite "Test Node - Host contracts":
fetchedBytes += blk.data.len.uint
return success()
(await onStore(request, 1.u256, onBlocks)).tryGet()
(await onStore(request, 1.uint64, onBlocks)).tryGet()
check fetchedBytes == 12 * DefaultBlockSize.uint
let indexer = verifiable.protectedStrategy.init(

View File

@ -157,10 +157,10 @@ asyncchecksuite "Test Node - Basic":
cid = manifestBlock.cid,
nodes = 5,
tolerance = 2,
duration = 100.u256,
duration = 100.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
expiry = 200.u256,
expiry = 200.uint64,
collateralPerByte = 1.u256,
)
).tryGet

View File

@ -3,6 +3,6 @@ import ../../helpers/mockclock
proc advanceToNextPeriod*(clock: MockClock, market: Market) {.async.} =
let periodicity = await market.periodicity()
let period = periodicity.periodOf(clock.now().u256)
let period = periodicity.periodOf(clock.now().Timestamp)
let periodEnd = periodicity.periodEnd(period)
clock.set((periodEnd + 1).truncate(int))
clock.set(periodEnd.toSecondsSince1970 + 1)

View File

@ -14,7 +14,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'cancelled'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let clock = MockClock.new()
let currentCollateral = UInt256.example

View File

@ -10,7 +10,7 @@ import ../../helpers
checksuite "sales state 'downloading'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
var state: SaleDownloading
setup:

View File

@ -14,7 +14,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'errored'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let market = MockMarket.new()
let clock = MockClock.new()

View File

@ -16,7 +16,7 @@ import ../../helpers
checksuite "sales state 'filled'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
var market: MockMarket
var slot: MockSlot

View File

@ -9,7 +9,7 @@ import ../../helpers
checksuite "sales state 'filling'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
var state: SaleFilling
setup:

View File

@ -15,7 +15,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'finished'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let clock = MockClock.new()
let currentCollateral = UInt256.example

View File

@ -14,7 +14,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'ignored'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let market = MockMarket.new()
let clock = MockClock.new()

View File

@ -20,7 +20,7 @@ import ../helpers/periods
asyncchecksuite "sales state 'initialproving'":
let proof = Groth16Proof.example
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let market = MockMarket.new()
let clock = MockClock.new()

View File

@ -15,7 +15,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'payout'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let clock = MockClock.new()
let currentCollateral = UInt256.example

View File

@ -22,7 +22,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'preparing'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let market = MockMarket.new()
let clock = MockClock.new()
var agent: SalesAgent
@ -34,9 +34,9 @@ asyncchecksuite "sales state 'preparing'":
setup:
availability = Availability.init(
totalSize = request.ask.slotSize + 100.u256,
freeSize = request.ask.slotSize + 100.u256,
duration = request.ask.duration + 60.u256,
totalSize = request.ask.slotSize + 100.uint64,
freeSize = request.ask.slotSize + 100.uint64,
duration = request.ask.duration + 60.uint64,
minPricePerBytePerSecond = request.ask.pricePerBytePerSecond,
totalCollateral = request.ask.collateralPerSlot * request.ask.slots.u256,
)

View File

@ -40,9 +40,9 @@ asyncchecksuite "sales state 'proving'":
proc advanceToNextPeriod(market: Market) {.async.} =
let periodicity = await market.periodicity()
let current = periodicity.periodOf(clock.now().u256)
let current = periodicity.periodOf(clock.now().Timestamp)
let periodEnd = periodicity.periodEnd(current)
clock.set(periodEnd.truncate(int64) + 1)
clock.set(periodEnd.toSecondsSince1970 + 1)
test "switches to cancelled state when request expires":
let next = state.onCancelled(request)

View File

@ -56,9 +56,9 @@ asyncchecksuite "sales state 'simulated-proving'":
proc advanceToNextPeriod(market: Market) {.async.} =
let periodicity = await market.periodicity()
let current = periodicity.periodOf(clock.now().u256)
let current = periodicity.periodOf(clock.now().Timestamp)
let periodEnd = periodicity.periodEnd(current)
clock.set(periodEnd.truncate(int64) + 1)
clock.set(periodEnd.toSecondsSince1970 + 1)
proc waitForProvingRounds(market: Market, rounds: int) {.async.} =
var rnds = rounds - 1 # proof round runs prior to advancing

View File

@ -19,7 +19,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'SlotReserving'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
var market: MockMarket
var clock: MockClock
var agent: SalesAgent

View File

@ -16,7 +16,7 @@ import ../../helpers
checksuite "sales state 'unknown'":
let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256
let slotIndex = request.ask.slots div 2
let slotId = slotId(request.id, slotIndex)
var market: MockMarket

View File

@ -41,17 +41,17 @@ asyncchecksuite "Reservations module":
proc createAvailability(): Availability =
let example = Availability.example(collateralPerByte)
let totalSize = rand(100000 .. 200000).u256
let totalCollateral = totalSize * collateralPerByte
let totalSize = rand(100000 .. 200000).uint64
let totalCollateral = totalSize.u256 * collateralPerByte
let availability = waitFor reservations.createAvailability(
totalSize, example.duration, example.minPricePerBytePerSecond, totalCollateral
)
return availability.get
proc createReservation(availability: Availability): Reservation =
let size = rand(1 ..< availability.freeSize.truncate(int))
let size = rand(1 ..< availability.freeSize.int)
let reservation = waitFor reservations.createReservation(
availability.id, size.u256, RequestId.example, UInt256.example, 1.u256
availability.id, size.uint64, RequestId.example, uint64.example, 1.u256
)
return reservation.get
@ -64,8 +64,8 @@ asyncchecksuite "Reservations module":
check (await reservations.all(Availability)).get.len == 0
test "generates unique ids for storage availability":
let availability1 = Availability.init(1.u256, 2.u256, 3.u256, 4.u256, 5.u256)
let availability2 = Availability.init(1.u256, 2.u256, 3.u256, 4.u256, 5.u256)
let availability1 = Availability.init(1.uint64, 2.uint64, 3.uint64, 4.u256, 5.u256)
let availability2 = Availability.init(1.uint64, 2.uint64, 3.uint64, 4.u256, 5.u256)
check availability1.id != availability2.id
test "can reserve available storage":
@ -75,7 +75,7 @@ asyncchecksuite "Reservations module":
test "creating availability reserves bytes in repo":
let orig = repo.available.uint
let availability = createAvailability()
check repo.available.uint == (orig.u256 - availability.freeSize).truncate(uint)
check repo.available.uint == orig - availability.freeSize
test "can get all availabilities":
let availability1 = createAvailability()
@ -129,7 +129,7 @@ asyncchecksuite "Reservations module":
test "cannot create reservation with non-existant availability":
let availability = Availability.example
let created = await reservations.createReservation(
availability.id, UInt256.example, RequestId.example, UInt256.example, 1.u256
availability.id, uint64.example, RequestId.example, uint64.example, 1.u256
)
check created.isErr
check created.error of NotExistsError
@ -140,7 +140,7 @@ asyncchecksuite "Reservations module":
availability.id,
availability.totalSize + 1,
RequestId.example,
UInt256.example,
uint64.example,
UInt256.example,
)
check created.isErr
@ -153,12 +153,12 @@ asyncchecksuite "Reservations module":
availability.id,
availability.totalSize - 1,
RequestId.example,
UInt256.example,
uint64.example,
UInt256.example,
)
let two = reservations.createReservation(
availability.id, availability.totalSize, RequestId.example, UInt256.example,
availability.id, availability.totalSize, RequestId.example, uint64.example,
UInt256.example,
)
@ -228,7 +228,7 @@ asyncchecksuite "Reservations module":
let reservation = createReservation(availability)
let orig = availability.freeSize - reservation.size
let origQuota = repo.quotaReservedBytes
let returnedBytes = reservation.size + 200.u256
let returnedBytes = reservation.size + 200.uint64
check isOk await reservations.returnBytesToAvailability(
reservation.availabilityId, reservation.id, returnedBytes
@ -238,7 +238,7 @@ asyncchecksuite "Reservations module":
let updated = !(await reservations.get(key, Availability))
check updated.freeSize > orig
check (updated.freeSize - orig) == 200.u256
check (updated.freeSize - orig) == 200.uint64
check (repo.quotaReservedBytes - origQuota) == 200.NBytes
test "update releases quota when lowering size":
@ -271,14 +271,14 @@ asyncchecksuite "Reservations module":
let availability = createAvailability()
let reservation = createReservation(availability)
let updated = await reservations.release(
reservation.id, reservation.availabilityId, (reservation.size + 1).truncate(uint)
reservation.id, reservation.availabilityId, reservation.size + 1
)
check updated.isErr
check updated.error of BytesOutOfBoundsError
test "cannot release bytes from non-existant reservation":
let availability = createAvailability()
let reservation = createReservation(availability)
discard createReservation(availability)
let updated = await reservations.release(ReservationId.example, availability.id, 1)
check updated.isErr
check updated.error of NotExistsError
@ -297,7 +297,7 @@ asyncchecksuite "Reservations module":
var added: Availability
reservations.onAvailabilityAdded = proc(a: Availability) {.async.} =
added = a
availability.freeSize += 1.u256
availability.freeSize += 1
discard await reservations.update(availability)
check added == availability
@ -307,7 +307,7 @@ asyncchecksuite "Reservations module":
var called = false
reservations.onAvailabilityAdded = proc(a: Availability) {.async.} =
called = true
availability.freeSize -= 1.u256
availability.freeSize -= 1
discard await reservations.update(availability)
check not called
@ -356,14 +356,11 @@ asyncchecksuite "Reservations module":
check reservations.hasAvailable(DefaultQuotaBytes.uint - 1)
test "reports quota not available to be reserved":
check not reservations.hasAvailable(DefaultQuotaBytes.uint + 1)
check not reservations.hasAvailable(DefaultQuotaBytes.uint64 + 1)
test "fails to create availability with size that is larger than available quota":
let created = await reservations.createAvailability(
(DefaultQuotaBytes.uint + 1).u256,
UInt256.example,
UInt256.example,
UInt256.example,
DefaultQuotaBytes.uint64 + 1, uint64.example, UInt256.example, UInt256.example
)
check created.isErr
check created.error of ReserveFailedError

View File

@ -42,15 +42,15 @@ asyncchecksuite "Sales - start":
request = StorageRequest(
ask: StorageAsk(
slots: 4,
slotSize: 100.u256,
duration: 60.u256,
slotSize: 100.uint64,
duration: 60.uint64,
pricePerBytePerSecond: 1.u256,
collateralPerByte: 1.u256,
),
content: StorageContent(
cid: Cid.init("zb2rhheVmk3bLks5MgzTqyznLu1zqGH5jrfTA1eAZXrjx7Vob").tryGet
),
expiry: (getTime() + initDuration(hours = 1)).toUnix.u256,
expiry: (getTime() + initDuration(hours = 1)).toUnix.uint64,
)
market = MockMarket.new()
@ -62,7 +62,7 @@ asyncchecksuite "Sales - start":
sales = Sales.new(market, clock, repo)
reservations = sales.context.reservations
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
return success()
@ -78,7 +78,7 @@ asyncchecksuite "Sales - start":
return success(proof)
itemsProcessed = @[]
expiry = (clock.now() + 42)
request.expiry = expiry.u256
request.expiry = expiry.uint64
teardown:
await sales.stop()
@ -86,7 +86,7 @@ asyncchecksuite "Sales - start":
await repoTmp.destroyDb()
await metaTmp.destroyDb()
proc fillSlot(slotIdx: UInt256 = 0.u256) {.async.} =
proc fillSlot(slotIdx: uint64 = 0.uint64) {.async.} =
let address = await market.getSigner()
let slot =
MockSlot(requestId: request.id, slotIndex: slotIdx, proof: proof, host: address)
@ -101,15 +101,13 @@ asyncchecksuite "Sales - start":
market.requestState[request.id] = RequestState.New
market.requestExpiry[request.id] = expiry
let slot0 =
MockSlot(requestId: request.id, slotIndex: 0.u256, proof: proof, host: me)
let slot0 = MockSlot(requestId: request.id, slotIndex: 0, proof: proof, host: me)
await fillSlot(slot0.slotIndex)
let slot1 =
MockSlot(requestId: request.id, slotIndex: 1.u256, proof: proof, host: me)
let slot1 = MockSlot(requestId: request.id, slotIndex: 1, proof: proof, host: me)
await fillSlot(slot1.slotIndex)
market.activeSlots[me] = @[request.slotId(0.u256), request.slotId(1.u256)]
market.activeSlots[me] = @[request.slotId(0), request.slotId(1)]
market.requested = @[request]
market.activeRequests[me] = @[request.id]
@ -117,10 +115,10 @@ asyncchecksuite "Sales - start":
check eventually sales.agents.len == 2
check sales.agents.any(
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.u256
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.uint64
)
check sales.agents.any(
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.u256
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.uint64
)
asyncchecksuite "Sales":
@ -129,7 +127,7 @@ asyncchecksuite "Sales":
repoTmp = TempLevelDb.new()
metaTmp = TempLevelDb.new()
var totalAvailabilitySize: UInt256
var totalAvailabilitySize: uint64
var minPricePerBytePerSecond: UInt256
var requestedCollateralPerByte: UInt256
var totalCollateral: UInt256
@ -144,29 +142,29 @@ asyncchecksuite "Sales":
var itemsProcessed: seq[SlotQueueItem]
setup:
totalAvailabilitySize = 100.u256
totalAvailabilitySize = 100.uint64
minPricePerBytePerSecond = 1.u256
requestedCollateralPerByte = 1.u256
totalCollateral = requestedCollateralPerByte * totalAvailabilitySize
totalCollateral = requestedCollateralPerByte * totalAvailabilitySize.stuint(256)
availability = Availability.init(
totalSize = totalAvailabilitySize,
freeSize = totalAvailabilitySize,
duration = 60.u256,
duration = 60.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = totalCollateral,
)
request = StorageRequest(
ask: StorageAsk(
slots: 4,
slotSize: 100.u256,
duration: 60.u256,
slotSize: 100.uint64,
duration: 60.uint64,
pricePerBytePerSecond: minPricePerBytePerSecond,
collateralPerByte: 1.u256,
),
content: StorageContent(
cid: Cid.init("zb2rhheVmk3bLks5MgzTqyznLu1zqGH5jrfTA1eAZXrjx7Vob").tryGet
),
expiry: (getTime() + initDuration(hours = 1)).toUnix.u256,
expiry: (getTime() + initDuration(hours = 1)).toUnix.uint64,
)
market = MockMarket.new()
@ -183,7 +181,7 @@ asyncchecksuite "Sales":
sales = Sales.new(market, clock, repo)
reservations = sales.context.reservations
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
return success()
@ -288,13 +286,13 @@ asyncchecksuite "Sales":
test "removes slot index from slot queue once SlotFilled emitted":
let request1 = await addRequestToSaturatedQueue()
market.emitSlotFilled(request1.id, 1.u256)
market.emitSlotFilled(request1.id, 1.uint64)
let expected = SlotQueueItem.init(request1, 1'u16)
check always (not itemsProcessed.contains(expected))
test "removes slot index from slot queue once SlotReservationsFull emitted":
let request1 = await addRequestToSaturatedQueue()
market.emitSlotReservationsFull(request1.id, 1.u256)
market.emitSlotReservationsFull(request1.id, 1.uint64)
let expected = SlotQueueItem.init(request1, 1'u16)
check always (not itemsProcessed.contains(expected))
@ -305,7 +303,7 @@ asyncchecksuite "Sales":
createAvailability()
market.requested.add request # "contract" must be able to return request
market.emitSlotFreed(request.id, 2.u256)
market.emitSlotFreed(request.id, 2.uint64)
let expected = SlotQueueItem.init(request, 2.uint16)
check eventually itemsProcessed.contains(expected)
@ -350,10 +348,10 @@ asyncchecksuite "Sales":
test "availability size is reduced by request slot size when fully downloaded":
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
let blk = bt.Block.new(@[1.byte]).get
await onBatch(blk.repeat(request.ask.slotSize.truncate(int)))
await onBatch(blk.repeat(request.ask.slotSize.int))
createAvailability()
await market.requestStorage(request)
@ -361,16 +359,16 @@ asyncchecksuite "Sales":
availability.freeSize - request.ask.slotSize
test "non-downloaded bytes are returned to availability once finished":
var slotIndex = 0.u256
var slotIndex = 0.uint64
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
slotIndex = slot
let blk = bt.Block.new(@[1.byte]).get
await onBatch(@[blk])
let sold = newFuture[void]()
sales.onSale = proc(request: StorageRequest, slotIndex: UInt256) =
sales.onSale = proc(request: StorageRequest, slotIndex: uint64) =
sold.complete()
createAvailability()
@ -381,7 +379,7 @@ asyncchecksuite "Sales":
# complete request
market.slotState[request.slotId(slotIndex)] = SlotState.Finished
clock.advance(request.ask.duration.truncate(int64))
clock.advance(request.ask.duration.int64)
check eventually getAvailability().freeSize == origSize - 1
@ -413,17 +411,17 @@ asyncchecksuite "Sales":
test "ignores request when slot state is not free":
createAvailability()
await market.requestStorage(request)
market.slotState[request.slotId(0.u256)] = SlotState.Filled
market.slotState[request.slotId(1.u256)] = SlotState.Filled
market.slotState[request.slotId(2.u256)] = SlotState.Filled
market.slotState[request.slotId(3.u256)] = SlotState.Filled
market.slotState[request.slotId(0.uint64)] = SlotState.Filled
market.slotState[request.slotId(1.uint64)] = SlotState.Filled
market.slotState[request.slotId(2.uint64)] = SlotState.Filled
market.slotState[request.slotId(3.uint64)] = SlotState.Filled
check wasIgnored()
test "retrieves and stores data locally":
var storingRequest: StorageRequest
var storingSlot: UInt256
var storingSlot: uint64
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
storingRequest = request
storingSlot = slot
@ -431,12 +429,12 @@ asyncchecksuite "Sales":
createAvailability()
await market.requestStorage(request)
check eventually storingRequest == request
check storingSlot < request.ask.slots.u256
check storingSlot < request.ask.slots
test "makes storage available again when data retrieval fails":
let error = newException(IOError, "data retrieval failed")
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
return failure(error)
createAvailability()
@ -445,7 +443,7 @@ asyncchecksuite "Sales":
test "generates proof of storage":
var provingRequest: StorageRequest
var provingSlot: UInt256
var provingSlot: uint64
sales.onProve = proc(
slot: Slot, challenge: ProofChallenge
): Future[?!Groth16Proof] {.async.} =
@ -457,7 +455,7 @@ asyncchecksuite "Sales":
await allowRequestToStart()
check eventually provingRequest == request
check provingSlot < request.ask.slots.u256
check provingSlot < request.ask.slots
test "fills a slot":
createAvailability()
@ -466,14 +464,14 @@ asyncchecksuite "Sales":
check eventually market.filled.len > 0
check market.filled[0].requestId == request.id
check market.filled[0].slotIndex < request.ask.slots.u256
check market.filled[0].slotIndex < request.ask.slots
check market.filled[0].proof == proof
check market.filled[0].host == await market.getSigner()
test "calls onFilled when slot is filled":
var soldRequest = StorageRequest.default
var soldSlotIndex = UInt256.high
sales.onSale = proc(request: StorageRequest, slotIndex: UInt256) =
var soldSlotIndex = uint64.high
sales.onSale = proc(request: StorageRequest, slotIndex: uint64) =
soldRequest = request
soldSlotIndex = slotIndex
createAvailability()
@ -481,7 +479,7 @@ asyncchecksuite "Sales":
await allowRequestToStart()
check eventually soldRequest == request
check soldSlotIndex < request.ask.slots.u256
check soldSlotIndex < request.ask.slots
test "calls onClear when storage becomes available again":
# fail the proof intentionally to trigger `agent.finish(success=false)`,
@ -491,8 +489,8 @@ asyncchecksuite "Sales":
): Future[?!Groth16Proof] {.async.} =
raise newException(IOError, "proof failed")
var clearedRequest: StorageRequest
var clearedSlotIndex: UInt256
sales.onClear = proc(request: StorageRequest, slotIndex: UInt256) =
var clearedSlotIndex: uint64
sales.onClear = proc(request: StorageRequest, slotIndex: uint64) =
clearedRequest = request
clearedSlotIndex = slotIndex
createAvailability()
@ -500,19 +498,19 @@ asyncchecksuite "Sales":
await allowRequestToStart()
check eventually clearedRequest == request
check clearedSlotIndex < request.ask.slots.u256
check clearedSlotIndex < request.ask.slots
test "makes storage available again when other host fills the slot":
let otherHost = Address.example
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
await sleepAsync(chronos.hours(1))
return success()
createAvailability()
await market.requestStorage(request)
for slotIndex in 0 ..< request.ask.slots:
market.fillSlot(request.id, slotIndex.u256, proof, otherHost)
market.fillSlot(request.id, slotIndex.uint64, proof, otherHost)
check eventually (await reservations.all(Availability)).get == @[availability]
test "makes storage available again when request expires":
@ -521,7 +519,7 @@ asyncchecksuite "Sales":
let origSize = availability.freeSize
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
await sleepAsync(chronos.hours(1))
return success()
@ -541,12 +539,12 @@ asyncchecksuite "Sales":
# ensure only one slot, otherwise once bytes are returned to the
# availability, the queue will be unpaused and availability will be consumed
# by other slots
request.ask.slots = 1.uint64
request.ask.slots = 1
market.requestExpiry[request.id] = expiry
let origSize = availability.freeSize
sales.onStore = proc(
request: StorageRequest, slot: UInt256, onBatch: BatchProc
request: StorageRequest, slot: uint64, onBatch: BatchProc
): Future[?!void] {.async.} =
await sleepAsync(chronos.hours(1))
return success()
@ -573,21 +571,19 @@ asyncchecksuite "Sales":
market.requestState[request.id] = RequestState.New
market.requestEnds[request.id] = request.expiry.toSecondsSince1970
proc fillSlot(slotIdx: UInt256 = 0.u256) {.async.} =
proc fillSlot(slotIdx: uint64 = 0) {.async.} =
let address = await market.getSigner()
let slot =
MockSlot(requestId: request.id, slotIndex: slotIdx, proof: proof, host: address)
market.filled.add slot
market.slotState[slotId(request.id, slotIdx)] = SlotState.Filled
let slot0 =
MockSlot(requestId: request.id, slotIndex: 0.u256, proof: proof, host: me)
let slot0 = MockSlot(requestId: request.id, slotIndex: 0, proof: proof, host: me)
await fillSlot(slot0.slotIndex)
let slot1 =
MockSlot(requestId: request.id, slotIndex: 1.u256, proof: proof, host: me)
let slot1 = MockSlot(requestId: request.id, slotIndex: 1, proof: proof, host: me)
await fillSlot(slot1.slotIndex)
market.activeSlots[me] = @[request.slotId(0.u256), request.slotId(1.u256)]
market.activeSlots[me] = @[request.slotId(0), request.slotId(1)]
market.requested = @[request]
market.activeRequests[me] = @[request.id]
@ -595,16 +591,16 @@ asyncchecksuite "Sales":
check eventually sales.agents.len == 2
check sales.agents.any(
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.u256
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.uint64
)
check sales.agents.any(
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.u256
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.uint64
)
test "deletes inactive reservations on load":
createAvailability()
discard await reservations.createReservation(
availability.id, 100.u256, RequestId.example, UInt256.example, UInt256.example
availability.id, 100.uint64, RequestId.example, 0.uint64, UInt256.example
)
check (await reservations.all(Reservation)).get.len == 1
await sales.load()

View File

@ -27,7 +27,7 @@ method onFailed*(state: MockState, request: StorageRequest): ?State =
onFailedCalled = true
method onSlotFilled*(
state: MockState, requestId: RequestId, slotIndex: UInt256
state: MockState, requestId: RequestId, slotIndex: uint64
): ?State =
onSlotFilledCalled = true
@ -35,17 +35,16 @@ asyncchecksuite "Sales agent":
let request = StorageRequest.example
var agent: SalesAgent
var context: SalesContext
var slotIndex: UInt256
var slotIndex: uint64
var market: MockMarket
var clock: MockClock
setup:
market = MockMarket.new()
market.requestExpiry[request.id] =
getTime().toUnix() + request.expiry.truncate(int64)
market.requestExpiry[request.id] = getTime().toUnix() + request.expiry.int64
clock = MockClock.new()
context = SalesContext(market: market, clock: clock)
slotIndex = 0.u256
slotIndex = 0.uint64
onCancelCalled = false
onFailedCalled = false
onSlotFilledCalled = false

View File

@ -146,18 +146,18 @@ suite "Slot queue":
test "correctly compares SlotQueueItems":
var requestA = StorageRequest.example
requestA.ask.duration = 1.u256
requestA.ask.duration = 1.uint64
requestA.ask.pricePerBytePerSecond = 1.u256
check requestA.ask.pricePerSlot == 1.u256 * requestA.ask.slotSize
check requestA.ask.pricePerSlot == 1.u256 * requestA.ask.slotSize.u256
requestA.ask.collateralPerByte = 100000.u256
requestA.expiry = 1001.u256
requestA.expiry = 1001.uint64
var requestB = StorageRequest.example
requestB.ask.duration = 100.u256
requestB.ask.duration = 100.uint64
requestB.ask.pricePerBytePerSecond = 1000.u256
check requestB.ask.pricePerSlot == 100000.u256 * requestB.ask.slotSize
check requestB.ask.pricePerSlot == 100000.u256 * requestB.ask.slotSize.u256
requestB.ask.collateralPerByte = 1.u256
requestB.expiry = 1000.u256
requestB.expiry = 1000.uint64
let itemA = SlotQueueItem.init(requestA, 0)
let itemB = SlotQueueItem.init(requestB, 0)
@ -169,21 +169,21 @@ suite "Slot queue":
let itemA = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256,
duration: 1.u256,
slotSize: 1.uint64,
duration: 1.uint64,
pricePerBytePerSecond: 2.u256, # profitability is higher (good)
collateralPerByte: 1.u256,
expiry: 1.u256,
expiry: 1.uint64,
seen: true, # seen (bad), more weight than profitability
)
let itemB = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256,
duration: 1.u256,
slotSize: 1.uint64,
duration: 1.uint64,
pricePerBytePerSecond: 1.u256, # profitability is lower (bad)
collateralPerByte: 1.u256,
expiry: 1.u256,
expiry: 1.uint64,
seen: false, # not seen (good)
)
check itemB.toSlotQueueItem < itemA.toSlotQueueItem # B higher priority than A
@ -194,22 +194,22 @@ suite "Slot queue":
let itemA = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256,
duration: 1.u256,
slotSize: 1.uint64,
duration: 1.uint64,
pricePerBytePerSecond: 1.u256, # reward is lower (bad)
collateralPerByte: 1.u256, # collateral is lower (good)
expiry: 1.u256,
expiry: 1.uint64,
seen: false,
)
let itemB = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256,
duration: 1.u256,
slotSize: 1.uint64,
duration: 1.uint64,
pricePerBytePerSecond: 2.u256,
# reward is higher (good), more weight than collateral
collateralPerByte: 2.u256, # collateral is higher (bad)
expiry: 1.u256,
expiry: 1.uint64,
seen: false,
)
@ -220,21 +220,21 @@ suite "Slot queue":
let itemA = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256,
duration: 1.u256,
slotSize: 1.uint64,
duration: 1.uint64,
pricePerBytePerSecond: 1.u256,
collateralPerByte: 2.u256, # collateral is higher (bad)
expiry: 2.u256, # expiry is longer (good)
expiry: 2.uint64, # expiry is longer (good)
seen: false,
)
let itemB = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256,
duration: 1.u256,
slotSize: 1.uint64,
duration: 1.uint64,
pricePerBytePerSecond: 1.u256,
collateralPerByte: 1.u256, # collateral is lower (good), more weight than expiry
expiry: 1.u256, # expiry is shorter (bad)
expiry: 1.uint64, # expiry is shorter (bad)
seen: false,
)
@ -245,21 +245,21 @@ suite "Slot queue":
let itemA = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256, # slotSize is smaller (good)
duration: 1.u256,
slotSize: 1.uint64, # slotSize is smaller (good)
duration: 1.uint64,
pricePerBytePerSecond: 1.u256,
collateralPerByte: 1.u256,
expiry: 1.u256, # expiry is shorter (bad)
expiry: 1.uint64, # expiry is shorter (bad)
seen: false,
)
let itemB = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 2.u256, # slotSize is larger (bad)
duration: 1.u256,
slotSize: 2.uint64, # slotSize is larger (bad)
duration: 1.uint64,
pricePerBytePerSecond: 1.u256,
collateralPerByte: 1.u256,
expiry: 2.u256, # expiry is longer (good), more weight than slotSize
expiry: 2.uint64, # expiry is longer (good), more weight than slotSize
seen: false,
)
@ -270,21 +270,21 @@ suite "Slot queue":
let itemA = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 2.u256, # slotSize is larger (bad)
duration: 1.u256,
slotSize: 2.uint64, # slotSize is larger (bad)
duration: 1.uint64,
pricePerBytePerSecond: 1.u256,
collateralPerByte: 1.u256,
expiry: 1.u256, # expiry is shorter (bad)
expiry: 1.uint64, # expiry is shorter (bad)
seen: false,
)
let itemB = MockSlotQueueItem(
requestId: request.id,
slotIndex: 0,
slotSize: 1.u256, # slotSize is smaller (good)
duration: 1.u256,
slotSize: 1.uint64, # slotSize is smaller (good)
duration: 1.uint64,
pricePerBytePerSecond: 1.u256,
collateralPerByte: 1.u256,
expiry: 1.u256,
expiry: 1.uint64,
seen: false,
)
@ -460,14 +460,14 @@ suite "Slot queue":
test "sorts items by expiry descending (longer expiry = higher priority)":
var request = StorageRequest.example
let item0 = SlotQueueItem.init(request, 0)
request.expiry += 1.u256
request.expiry += 1
let item1 = SlotQueueItem.init(request, 1)
check item1 < item0
test "sorts items by slot size descending (bigger dataset = higher profitability = higher priority)":
var request = StorageRequest.example
let item0 = SlotQueueItem.init(request, 0)
request.ask.slotSize += 1.u256
request.ask.slotSize += 1
let item1 = SlotQueueItem.init(request, 1)
check item1 < item0

View File

@ -28,8 +28,8 @@ asyncchecksuite "Purchasing":
request = StorageRequest(
ask: StorageAsk(
slots: uint8.example.uint64,
slotSize: uint32.example.u256,
duration: uint16.example.u256,
slotSize: uint32.example.uint64,
duration: uint16.example.uint64,
pricePerBytePerSecond: uint8.example.u256,
)
)
@ -100,7 +100,6 @@ asyncchecksuite "Purchasing":
market.requestExpiry[populatedRequest.id] = expiry
let purchase = await purchasing.purchase(populatedRequest)
check eventually market.requested.len > 0
let request = market.requested[0]
clock.set(expiry + 1)
expect PurchaseTimeout:
@ -130,8 +129,8 @@ checksuite "Purchasing state machine":
request = StorageRequest(
ask: StorageAsk(
slots: uint8.example.uint64,
slotSize: uint32.example.u256,
duration: uint16.example.u256,
slotSize: uint32.example.uint64,
duration: uint16.example.uint64,
pricePerBytePerSecond: uint8.example.u256,
)
)
@ -185,7 +184,7 @@ checksuite "Purchasing state machine":
test "moves to PurchaseStarted when request state is Started":
let request = StorageRequest.example
let purchase = Purchase.new(request, market, clock)
market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64)
market.requestEnds[request.id] = clock.now() + request.ask.duration.int64
market.requested = @[request]
market.requestState[request.id] = RequestState.Started
let next = await PurchaseUnknown().run(purchase)
@ -218,7 +217,7 @@ checksuite "Purchasing state machine":
test "moves to PurchaseFailed state once RequestFailed emitted":
let request = StorageRequest.example
let purchase = Purchase.new(request, market, clock)
market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64)
market.requestEnds[request.id] = clock.now() + request.ask.duration.int64
let future = PurchaseStarted().run(purchase)
market.emitRequestFailed(request.id)
@ -229,10 +228,10 @@ checksuite "Purchasing state machine":
test "moves to PurchaseFinished state once request finishes":
let request = StorageRequest.example
let purchase = Purchase.new(request, market, clock)
market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64)
market.requestEnds[request.id] = clock.now() + request.ask.duration.int64
let future = PurchaseStarted().run(purchase)
clock.advance(request.ask.duration.truncate(int64) + 1)
clock.advance(request.ask.duration.int64 + 1)
let next = await future
check !next of PurchaseFinished

View File

@ -16,8 +16,8 @@ logScope:
topics = "testValidation"
asyncchecksuite "validation":
let period = 10
let timeout = 5
let period = 10.uint64
let timeout = 5.uint64
let maxSlots = MaxSlots(100)
let validationGroups = ValidationGroups(8).some
let slot = Slot.example
@ -51,8 +51,8 @@ asyncchecksuite "validation":
groupIndex = groupIndexForSlotId(slot.id, !validationGroups)
clock = MockClock.new()
market = MockMarket.new(clock = Clock(clock).some)
market.config.proofs.period = period.u256
market.config.proofs.timeout = timeout.u256
market.config.proofs.period = period
market.config.proofs.timeout = timeout
validation = newValidation(clock, market, maxSlots, validationGroups, groupIndex)
teardown:
@ -60,10 +60,10 @@ asyncchecksuite "validation":
await validation.stop()
proc advanceToNextPeriod() =
let periodicity = Periodicity(seconds: period.u256)
let period = periodicity.periodOf(clock.now().u256)
let periodicity = Periodicity(seconds: period)
let period = periodicity.periodOf(clock.now().Timestamp)
let periodEnd = periodicity.periodEnd(period)
clock.set((periodEnd + 1).truncate(int))
clock.set(periodEnd.toSecondsSince1970 + 1)
test "the list of slots that it's monitoring is empty initially":
check validation.slots.len == 0

View File

@ -49,28 +49,29 @@ ethersuite "Marketplace contracts":
switchAccount(host)
discard
await token.approve(marketplace.address, request.ask.collateralPerSlot).confirm(1)
discard await marketplace.reserveSlot(request.id, 0.u256).confirm(1)
let receipt = await marketplace.fillSlot(request.id, 0.u256, proof).confirm(1)
discard await marketplace.reserveSlot(request.id, 0.uint64).confirm(1)
let receipt = await marketplace.fillSlot(request.id, 0.uint64, proof).confirm(1)
filledAt = await ethProvider.blockTime(BlockTag.init(!receipt.blockNumber))
slotId = request.slotId(0.u256)
slotId = request.slotId(0.uint64)
proc waitUntilProofRequired(slotId: SlotId) {.async.} =
let currentPeriod = periodicity.periodOf(await ethProvider.currentTime())
await ethProvider.advanceTimeTo(periodicity.periodEnd(currentPeriod))
let currentPeriod =
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
await ethProvider.advanceTimeTo(periodicity.periodEnd(currentPeriod).u256)
while not (
(await marketplace.isProofRequired(slotId)) and
(await marketplace.getPointer(slotId)) < 250
)
:
await ethProvider.advanceTime(periodicity.seconds)
await ethProvider.advanceTime(periodicity.seconds.u256)
proc startContract() {.async.} =
for slotIndex in 1 ..< request.ask.slots:
discard await token
.approve(marketplace.address, request.ask.collateralPerSlot)
.confirm(1)
discard await marketplace.reserveSlot(request.id, slotIndex.u256).confirm(1)
discard await marketplace.fillSlot(request.id, slotIndex.u256, proof).confirm(1)
discard await marketplace.reserveSlot(request.id, slotIndex.uint64).confirm(1)
discard await marketplace.fillSlot(request.id, slotIndex.uint64, proof).confirm(1)
test "accept marketplace proofs":
switchAccount(host)
@ -80,9 +81,10 @@ ethersuite "Marketplace contracts":
test "can mark missing proofs":
switchAccount(host)
await waitUntilProofRequired(slotId)
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
let missingPeriod =
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
let endOfPeriod = periodicity.periodEnd(missingPeriod)
await ethProvider.advanceTimeTo(endOfPeriod + 1)
await ethProvider.advanceTimeTo(endOfPeriod.u256 + 1)
switchAccount(client)
discard await marketplace.markProofAsMissing(slotId, missingPeriod).confirm(1)
@ -123,7 +125,8 @@ ethersuite "Marketplace contracts":
let expiry = await marketplace.requestExpiry(request.id)
await ethProvider.advanceTimeTo((expiry + 1).u256)
switchAccount(client)
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
await ethProvider.advanceTime(periodicity.seconds)
let missingPeriod =
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
await ethProvider.advanceTime(periodicity.seconds.u256)
expect Marketplace_SlotNotAcceptingProofs:
discard await marketplace.markProofAsMissing(slotId, missingPeriod).confirm(1)

View File

@ -25,7 +25,7 @@ ethersuite "On-Chain Market":
var marketplace: Marketplace
var token: Erc20Token
var request: StorageRequest
var slotIndex: UInt256
var slotIndex: uint64
var periodicity: Periodicity
var host: Signer
var otherHost: Signer
@ -58,11 +58,12 @@ ethersuite "On-Chain Market":
host = ethProvider.getSigner(accounts[1])
otherHost = ethProvider.getSigner(accounts[3])
slotIndex = (request.ask.slots div 2).u256
slotIndex = request.ask.slots div 2
proc advanceToNextPeriod() {.async.} =
let currentPeriod = periodicity.periodOf(await ethProvider.currentTime())
await ethProvider.advanceTimeTo(periodicity.periodEnd(currentPeriod) + 1)
let currentPeriod =
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
await ethProvider.advanceTimeTo((periodicity.periodEnd(currentPeriod) + 1).u256)
proc advanceToCancelledRequest(request: StorageRequest) {.async.} =
let expiry = (await market.requestExpiresAt(request.id)) + 1
@ -125,12 +126,13 @@ ethersuite "On-Chain Market":
test "supports request subscriptions":
var receivedIds: seq[RequestId]
var receivedAsks: seq[StorageAsk]
proc onRequest(id: RequestId, ask: StorageAsk, expiry: UInt256) =
proc onRequest(id: RequestId, ask: StorageAsk, expiry: uint64) =
receivedIds.add(id)
receivedAsks.add(ask)
let subscription = await market.subscribeRequests(onRequest)
await market.requestStorage(request)
check eventually receivedIds == @[request.id] and receivedAsks == @[request.ask]
await subscription.unsubscribe()
@ -172,7 +174,8 @@ ethersuite "On-Chain Market":
await market.reserveSlot(request.id, slotIndex)
await market.fillSlot(request.id, slotIndex, proof, request.ask.collateralPerSlot)
await waitUntilProofRequired(slotId)
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
let missingPeriod =
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
await advanceToNextPeriod()
await market.markProofAsMissing(slotId, missingPeriod)
check (await marketplace.missingProofs(slotId)) == 1
@ -183,15 +186,16 @@ ethersuite "On-Chain Market":
await market.reserveSlot(request.id, slotIndex)
await market.fillSlot(request.id, slotIndex, proof, request.ask.collateralPerSlot)
await waitUntilProofRequired(slotId)
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
let missingPeriod =
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
await advanceToNextPeriod()
check (await market.canProofBeMarkedAsMissing(slotId, missingPeriod)) == true
test "supports slot filled subscriptions":
await market.requestStorage(request)
var receivedIds: seq[RequestId]
var receivedSlotIndices: seq[UInt256]
proc onSlotFilled(id: RequestId, slotIndex: UInt256) =
var receivedSlotIndices: seq[uint64]
proc onSlotFilled(id: RequestId, slotIndex: uint64) =
receivedIds.add(id)
receivedSlotIndices.add(slotIndex)
@ -206,8 +210,8 @@ ethersuite "On-Chain Market":
test "subscribes only to a certain slot":
var otherSlot = slotIndex - 1
await market.requestStorage(request)
var receivedSlotIndices: seq[UInt256]
proc onSlotFilled(requestId: RequestId, slotIndex: UInt256) =
var receivedSlotIndices: seq[uint64]
proc onSlotFilled(requestId: RequestId, slotIndex: uint64) =
receivedSlotIndices.add(slotIndex)
let subscription =
@ -224,8 +228,8 @@ ethersuite "On-Chain Market":
await market.reserveSlot(request.id, slotIndex)
await market.fillSlot(request.id, slotIndex, proof, request.ask.collateralPerSlot)
var receivedRequestIds: seq[RequestId] = @[]
var receivedIdxs: seq[UInt256] = @[]
proc onSlotFreed(requestId: RequestId, idx: UInt256) =
var receivedIdxs: seq[uint64] = @[]
proc onSlotFreed(requestId: RequestId, idx: uint64) =
receivedRequestIds.add(requestId)
receivedIdxs.add(idx)
@ -243,8 +247,8 @@ ethersuite "On-Chain Market":
await market.requestStorage(request)
var receivedRequestIds: seq[RequestId] = @[]
var receivedIdxs: seq[UInt256] = @[]
proc onSlotReservationsFull(requestId: RequestId, idx: UInt256) =
var receivedIdxs: seq[uint64] = @[]
proc onSlotReservationsFull(requestId: RequestId, idx: uint64) =
receivedRequestIds.add(requestId)
receivedIdxs.add(idx)
@ -270,9 +274,9 @@ ethersuite "On-Chain Market":
let subscription = await market.subscribeFulfillment(request.id, onFulfillment)
for slotIndex in 0 ..< request.ask.slots:
await market.reserveSlot(request.id, slotIndex.u256)
await market.reserveSlot(request.id, slotIndex.uint64)
await market.fillSlot(
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
)
check eventually receivedIds == @[request.id]
await subscription.unsubscribe()
@ -291,14 +295,14 @@ ethersuite "On-Chain Market":
let subscription = await market.subscribeFulfillment(request.id, onFulfillment)
for slotIndex in 0 ..< request.ask.slots:
await market.reserveSlot(request.id, slotIndex.u256)
await market.reserveSlot(request.id, slotIndex.uint64)
await market.fillSlot(
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
)
for slotIndex in 0 ..< otherRequest.ask.slots:
await market.reserveSlot(otherRequest.id, slotIndex.u256)
await market.reserveSlot(otherRequest.id, slotIndex.uint64)
await market.fillSlot(
otherRequest.id, slotIndex.u256, proof, otherRequest.ask.collateralPerSlot
otherRequest.id, slotIndex.uint64, proof, otherRequest.ask.collateralPerSlot
)
check eventually receivedIds == @[request.id]
@ -330,18 +334,19 @@ ethersuite "On-Chain Market":
let subscription = await market.subscribeRequestFailed(request.id, onRequestFailed)
for slotIndex in 0 ..< request.ask.slots:
await market.reserveSlot(request.id, slotIndex.u256)
await market.reserveSlot(request.id, slotIndex.uint64)
await market.fillSlot(
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
)
for slotIndex in 0 .. request.ask.maxSlotLoss:
let slotId = request.slotId(slotIndex.u256)
let slotId = request.slotId(slotIndex.uint64)
while true:
let slotState = await marketplace.slotState(slotId)
if slotState == SlotState.Repair or slotState == SlotState.Failed:
break
await waitUntilProofRequired(slotId)
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
let missingPeriod =
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
await advanceToNextPeriod()
discard await marketplace.markProofAsMissing(slotId, missingPeriod).confirm(1)
check eventually receivedIds == @[request.id]
@ -395,9 +400,9 @@ ethersuite "On-Chain Market":
test "can retrieve request state":
await market.requestStorage(request)
for slotIndex in 0 ..< request.ask.slots:
await market.reserveSlot(request.id, slotIndex.u256)
await market.reserveSlot(request.id, slotIndex.uint64)
await market.fillSlot(
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
)
check (await market.requestState(request.id)) == some RequestState.Started
@ -460,13 +465,12 @@ ethersuite "On-Chain Market":
test "can query past SlotFilled events":
await market.requestStorage(request)
await market.reserveSlot(request.id, 0.u256)
await market.reserveSlot(request.id, 1.u256)
await market.reserveSlot(request.id, 2.u256)
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 1.u256, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 2.u256, proof, request.ask.collateralPerSlot)
let slotId = request.slotId(slotIndex)
await market.reserveSlot(request.id, 0.uint64)
await market.reserveSlot(request.id, 1.uint64)
await market.reserveSlot(request.id, 2.uint64)
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 1.uint64, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 2.uint64, proof, request.ask.collateralPerSlot)
# `market.fill` executes an `approve` tx before the `fillSlot` tx, so that's
# two PoA blocks per `fillSlot` call (6 blocks for 3 calls). We don't need
@ -475,15 +479,15 @@ ethersuite "On-Chain Market":
let events = await market.queryPastSlotFilledEvents(blocksAgo = 5)
check events ==
@[
SlotFilled(requestId: request.id, slotIndex: 0.u256),
SlotFilled(requestId: request.id, slotIndex: 1.u256),
SlotFilled(requestId: request.id, slotIndex: 2.u256),
SlotFilled(requestId: request.id, slotIndex: 0),
SlotFilled(requestId: request.id, slotIndex: 1),
SlotFilled(requestId: request.id, slotIndex: 2),
]
test "can query past SlotFilled events since given timestamp":
await market.requestStorage(request)
await market.reserveSlot(request.id, 0.u256)
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
await market.reserveSlot(request.id, 0.uint64)
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
# The SlotFilled event will be included in the same block as
# the fillSlot transaction. If we want to ignore the SlotFilled event
@ -494,10 +498,10 @@ ethersuite "On-Chain Market":
let (_, fromTime) = await ethProvider.blockNumberAndTimestamp(BlockTag.latest)
await market.reserveSlot(request.id, 1.u256)
await market.reserveSlot(request.id, 2.u256)
await market.fillSlot(request.id, 1.u256, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 2.u256, proof, request.ask.collateralPerSlot)
await market.reserveSlot(request.id, 1.uint64)
await market.reserveSlot(request.id, 2.uint64)
await market.fillSlot(request.id, 1.uint64, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 2.uint64, proof, request.ask.collateralPerSlot)
let events = await market.queryPastSlotFilledEvents(
fromTime = fromTime.truncate(SecondsSince1970)
@ -505,19 +509,19 @@ ethersuite "On-Chain Market":
check events ==
@[
SlotFilled(requestId: request.id, slotIndex: 1.u256),
SlotFilled(requestId: request.id, slotIndex: 2.u256),
SlotFilled(requestId: request.id, slotIndex: 1),
SlotFilled(requestId: request.id, slotIndex: 2),
]
test "queryPastSlotFilledEvents returns empty sequence of events when " &
"no SlotFilled events have occurred since given timestamp":
await market.requestStorage(request)
await market.reserveSlot(request.id, 0.u256)
await market.reserveSlot(request.id, 1.u256)
await market.reserveSlot(request.id, 2.u256)
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 1.u256, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 2.u256, proof, request.ask.collateralPerSlot)
await market.reserveSlot(request.id, 0.uint64)
await market.reserveSlot(request.id, 1.uint64)
await market.reserveSlot(request.id, 2.uint64)
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 1.uint64, proof, request.ask.collateralPerSlot)
await market.fillSlot(request.id, 2.uint64, proof, request.ask.collateralPerSlot)
await ethProvider.advanceTime(10.u256)
@ -542,21 +546,21 @@ ethersuite "On-Chain Market":
let address = await host.getAddress()
switchAccount(host)
await market.reserveSlot(request.id, 0.u256)
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
await market.reserveSlot(request.id, 0.uint64)
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
let filledAt = (await ethProvider.currentTime()) - 1.u256
for slotIndex in 1 ..< request.ask.slots:
await market.reserveSlot(request.id, slotIndex.u256)
await market.reserveSlot(request.id, slotIndex.uint64)
await market.fillSlot(
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
)
let requestEnd = await market.getRequestEnd(request.id)
await ethProvider.advanceTimeTo(requestEnd.u256 + 1)
let startBalance = await token.balanceOf(address)
await market.freeSlot(request.slotId(0.u256))
await market.freeSlot(request.slotId(0.uint64))
let endBalance = await token.balanceOf(address)
let expectedPayout = request.expectedPayout(filledAt, requestEnd.u256)
@ -569,14 +573,14 @@ ethersuite "On-Chain Market":
await market.requestStorage(request)
switchAccount(host)
await market.reserveSlot(request.id, 0.u256)
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
await market.reserveSlot(request.id, 0.uint64)
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
let filledAt = (await ethProvider.currentTime()) - 1.u256
for slotIndex in 1 ..< request.ask.slots:
await market.reserveSlot(request.id, slotIndex.u256)
await market.reserveSlot(request.id, slotIndex.uint64)
await market.fillSlot(
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
)
let requestEnd = await market.getRequestEnd(request.id)
@ -585,7 +589,7 @@ ethersuite "On-Chain Market":
let startBalanceHost = await token.balanceOf(hostAddress)
let startBalanceReward = await token.balanceOf(hostRewardRecipient)
await market.freeSlot(request.slotId(0.u256))
await market.freeSlot(request.slotId(0.uint64))
let endBalanceHost = await token.balanceOf(hostAddress)
let endBalanceReward = await token.balanceOf(hostRewardRecipient)

View File

@ -49,8 +49,8 @@ proc example*(_: type StorageRequest): StorageRequest =
client: Address.example,
ask: StorageAsk(
slots: 4,
slotSize: (1 * 1024 * 1024 * 1024).u256, # 1 Gigabyte
duration: (10 * 60 * 60).u256, # 10 hours
slotSize: (1 * 1024 * 1024 * 1024).uint64, # 1 Gigabyte
duration: (10 * 60 * 60).uint64, # 10 hours
collateralPerByte: 1.u256,
proofProbability: 4.u256, # require a proof roughly once every 4 periods
pricePerBytePerSecond: 1.u256,
@ -60,19 +60,19 @@ proc example*(_: type StorageRequest): StorageRequest =
cid: Cid.init("zb2rhheVmk3bLks5MgzTqyznLu1zqGH5jrfTA1eAZXrjx7Vob").tryGet,
merkleRoot: array[32, byte].example,
),
expiry: (60 * 60).u256, # 1 hour ,
expiry: (60 * 60).uint64, # 1 hour ,
nonce: Nonce.example,
)
proc example*(_: type Slot): Slot =
let request = StorageRequest.example
let slotIndex = rand(request.ask.slots.int).u256
let slotIndex = rand(request.ask.slots.int).uint64
Slot(request: request, slotIndex: slotIndex)
proc example*(_: type SlotQueueItem): SlotQueueItem =
let request = StorageRequest.example
let slot = Slot.example
SlotQueueItem.init(request, slot.slotIndex.truncate(uint16))
SlotQueueItem.init(request, slot.slotIndex.uint16)
proc example(_: type G1Point): G1Point =
G1Point(x: UInt256.example, y: UInt256.example)

View File

@ -117,11 +117,11 @@ proc space*(client: CodexClient): ?!RestRepoStore =
proc requestStorageRaw*(
client: CodexClient,
cid: Cid,
duration: UInt256,
duration: uint64,
pricePerBytePerSecond: UInt256,
proofProbability: UInt256,
collateralPerByte: UInt256,
expiry: uint = 0,
expiry: uint64 = 0,
nodes: uint = 3,
tolerance: uint = 1,
): Response =
@ -146,10 +146,10 @@ proc requestStorageRaw*(
proc requestStorage*(
client: CodexClient,
cid: Cid,
duration: UInt256,
duration: uint64,
pricePerBytePerSecond: UInt256,
proofProbability: UInt256,
expiry: uint,
expiry: uint64,
collateralPerByte: UInt256,
nodes: uint = 3,
tolerance: uint = 1,
@ -187,7 +187,8 @@ proc getSlots*(client: CodexClient): ?!seq[Slot] =
proc postAvailability*(
client: CodexClient,
totalSize, duration, minPricePerBytePerSecond, totalCollateral: UInt256,
totalSize, duration: uint64,
minPricePerBytePerSecond, totalCollateral: UInt256,
): ?!Availability =
## Post sales availability endpoint
##
@ -207,8 +208,8 @@ proc postAvailability*(
proc patchAvailabilityRaw*(
client: CodexClient,
availabilityId: AvailabilityId,
totalSize, freeSize, duration, minPricePerBytePerSecond, totalCollateral: ?UInt256 =
UInt256.none,
totalSize, freeSize, duration: ?uint64 = uint64.none,
minPricePerBytePerSecond, totalCollateral: ?UInt256 = UInt256.none,
): Response =
## Updates availability
##
@ -237,8 +238,8 @@ proc patchAvailabilityRaw*(
proc patchAvailability*(
client: CodexClient,
availabilityId: AvailabilityId,
totalSize, duration, minPricePerBytePerSecond, totalCollateral: ?UInt256 =
UInt256.none,
totalSize, duration: ?uint64 = uint64.none,
minPricePerBytePerSecond, totalCollateral: ?UInt256 = UInt256.none,
): void =
let response = client.patchAvailabilityRaw(
availabilityId,

View File

@ -20,14 +20,14 @@ template marketplacesuite*(name: string, body: untyped) =
var token {.inject, used.}: Erc20Token
proc getCurrentPeriod(): Future[Period] {.async.} =
return periodicity.periodOf(await ethProvider.currentTime())
return periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
proc advanceToNextPeriod() {.async.} =
let periodicity = Periodicity(seconds: period.u256)
let currentTime = await ethProvider.currentTime()
let periodicity = Periodicity(seconds: period)
let currentTime = (await ethProvider.currentTime()).truncate(uint64)
let currentPeriod = periodicity.periodOf(currentTime)
let endOfPeriod = periodicity.periodEnd(currentPeriod)
await ethProvider.advanceTimeTo(endOfPeriod + 1)
await ethProvider.advanceTimeTo(endOfPeriod.u256 + 1)
template eventuallyP(condition: untyped, finalPeriod: Period): bool =
proc eventuallyP(): Future[bool] {.async.} =
@ -56,19 +56,19 @@ template marketplacesuite*(name: string, body: untyped) =
return nodes.u256 * slotSize(blocks, nodes, tolerance)
proc createAvailabilities(
datasetSize: UInt256,
datasetSize: uint64,
duration: uint64,
collateralPerByte: UInt256,
minPricePerBytePerSecond: UInt256,
) =
let totalCollateral = datasetSize * collateralPerByte
let totalCollateral = datasetSize.u256 * collateralPerByte
# post availability to each provider
for i in 0 ..< providers().len:
let provider = providers()[i].client
discard provider.postAvailability(
totalSize = datasetSize,
duration = duration.u256,
duration = duration.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = totalCollateral,
)
@ -76,7 +76,7 @@ template marketplacesuite*(name: string, body: untyped) =
proc requestStorage(
client: CodexClient,
cid: Cid,
proofProbability = 1,
proofProbability = 1.u256,
duration: uint64 = 12.periods,
pricePerBytePerSecond = 1.u256,
collateralPerByte = 1.u256,
@ -86,9 +86,9 @@ template marketplacesuite*(name: string, body: untyped) =
): Future[PurchaseId] {.async.} =
let id = client.requestStorage(
cid,
expiry = expiry.uint,
duration = duration.u256,
proofProbability = proofProbability.u256,
expiry = expiry,
duration = duration,
proofProbability = proofProbability,
collateralPerByte = collateralPerByte,
pricePerBytePerSecond = pricePerBytePerSecond,
nodes = nodes.uint,
@ -102,7 +102,7 @@ template marketplacesuite*(name: string, body: untyped) =
let tokenAddress = await marketplace.token()
token = Erc20Token.new(tokenAddress, ethProvider.getSigner())
let config = await marketplace.configuration()
period = config.proofs.period.truncate(uint64)
periodicity = Periodicity(seconds: period.u256)
period = config.proofs.period
periodicity = Periodicity(seconds: period)
body

View File

@ -34,28 +34,28 @@ marketplacesuite "Marketplace":
await ethProvider.advanceTime(1.u256)
test "nodes negotiate contracts on the marketplace", marketplaceConfig:
let size = 0xFFFFFF.u256
let size = 0xFFFFFF.uint64
let data = await RandomChunker.example(blocks = blocks)
# host makes storage available
let availability = host.postAvailability(
totalSize = size,
duration = 20 * 60.u256,
duration = 20 * 60.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = size * minPricePerBytePerSecond,
totalCollateral = size.u256 * minPricePerBytePerSecond,
).get
# client requests storage
let cid = client.upload(data).get
let id = client.requestStorage(
let id = await client.requestStorage(
cid,
duration = 20 * 60.u256,
duration = 20 * 60.uint64,
pricePerBytePerSecond = minPricePerBytePerSecond,
proofProbability = 3.u256,
expiry = 10 * 60,
expiry = 10 * 60.uint64,
collateralPerByte = collateralPerByte,
nodes = ecNodes,
tolerance = ecTolerance,
).get
)
check eventually(client.purchaseStateIs(id, "started"), timeout = 10 * 60 * 1000)
let purchase = client.getPurchase(id).get
@ -71,34 +71,34 @@ marketplacesuite "Marketplace":
test "node slots gets paid out and rest of tokens are returned to client",
marketplaceConfig:
let size = 0xFFFFFF.u256
let size = 0xFFFFFF.uint64
let data = await RandomChunker.example(blocks = blocks)
let marketplace = Marketplace.new(Marketplace.address, ethProvider.getSigner())
let tokenAddress = await marketplace.token()
let token = Erc20Token.new(tokenAddress, ethProvider.getSigner())
let duration = 20 * 60.u256
let duration = 20 * 60.uint64
# host makes storage available
let startBalanceHost = await token.balanceOf(hostAccount)
discard host.postAvailability(
totalSize = size,
duration = 20 * 60.u256,
duration = 20 * 60.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = size * minPricePerBytePerSecond,
totalCollateral = size.u256 * minPricePerBytePerSecond,
).get
# client requests storage
let cid = client.upload(data).get
let id = client.requestStorage(
let id = await client.requestStorage(
cid,
duration = duration,
pricePerBytePerSecond = minPricePerBytePerSecond,
proofProbability = 3.u256,
expiry = 10 * 60,
expiry = 10 * 60.uint64,
collateralPerByte = collateralPerByte,
nodes = ecNodes,
tolerance = ecTolerance,
).get
)
check eventually(client.purchaseStateIs(id, "started"), timeout = 10 * 60 * 1000)
let purchase = client.getPurchase(id).get
@ -109,13 +109,13 @@ marketplacesuite "Marketplace":
# Proving mechanism uses blockchain clock to do proving/collect/cleanup round
# hence we must use `advanceTime` over `sleepAsync` as Hardhat does mine new blocks
# only with new transaction
await ethProvider.advanceTime(duration)
await ethProvider.advanceTime(duration.u256)
# Checking that the hosting node received reward for at least the time between <expiry;end>
let slotSize = slotSize(blocks, ecNodes, ecTolerance)
let pricePerSlotPerSecond = minPricePerBytePerSecond * slotSize
check eventually (await token.balanceOf(hostAccount)) - startBalanceHost >=
(duration - 5 * 60) * pricePerSlotPerSecond * ecNodes.u256
(duration - 5 * 60).u256 * pricePerSlotPerSecond * ecNodes.u256
# Checking that client node receives some funds back that were not used for the host nodes
check eventually(
@ -157,19 +157,19 @@ marketplacesuite "Marketplace payouts":
# provider makes storage available
let datasetSize = datasetSize(blocks, ecNodes, ecTolerance)
let totalAvailabilitySize = datasetSize div 2
let totalAvailabilitySize = (datasetSize div 2).truncate(uint64)
discard providerApi.postAvailability(
# make availability size small enough that we can't fill all the slots,
# thus causing a cancellation
totalSize = totalAvailabilitySize,
duration = duration.u256,
duration = duration.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = collateralPerByte * totalAvailabilitySize,
totalCollateral = collateralPerByte * totalAvailabilitySize.u256,
)
let cid = clientApi.upload(data).get
var slotIdxFilled = none UInt256
var slotIdxFilled = none uint64
proc onSlotFilled(eventResult: ?!SlotFilled) =
assert not eventResult.isErr
slotIdxFilled = some (!eventResult).slotIndex

View File

@ -43,7 +43,10 @@ marketplacesuite "Hosts submit regular proofs":
let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
createAvailabilities(
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
datasetSize.truncate(uint64),
duration,
collateralPerByte,
minPricePerBytePerSecond,
)
let cid = client0.upload(data).get
@ -117,7 +120,10 @@ marketplacesuite "Simulate invalid proofs":
let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
createAvailabilities(
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
datasetSize.truncate(uint64),
duration,
collateralPerByte,
minPricePerBytePerSecond,
)
let cid = client0.upload(data).get
@ -128,7 +134,7 @@ marketplacesuite "Simulate invalid proofs":
duration = duration,
nodes = ecNodes,
tolerance = ecTolerance,
proofProbability = 1,
proofProbability = 1.u256,
)
let requestId = client0.requestId(purchaseId).get
@ -177,7 +183,10 @@ marketplacesuite "Simulate invalid proofs":
let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
createAvailabilities(
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
datasetSize.truncate(uint64),
duration,
collateralPerByte,
minPricePerBytePerSecond,
)
let cid = client0.upload(data).get
@ -188,7 +197,7 @@ marketplacesuite "Simulate invalid proofs":
duration = duration,
nodes = ecNodes,
tolerance = ecTolerance,
proofProbability = 1,
proofProbability = 1.u256,
)
let requestId = client0.requestId(purchaseId).get

View File

@ -11,18 +11,18 @@ twonodessuite "Purchasing":
let cid = client1.upload(data).get
let id1 = client1.requestStorage(
cid,
duration = 100.u256,
duration = 100.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
expiry = 10,
expiry = 10.uint64,
collateralPerByte = 1.u256,
).get
let id2 = client1.requestStorage(
cid,
duration = 400.u256,
duration = 400.uint64,
pricePerBytePerSecond = 2.u256,
proofProbability = 6.u256,
expiry = 10,
expiry = 10.uint64,
collateralPerByte = 2.u256,
).get
check id1 != id2
@ -37,10 +37,10 @@ twonodessuite "Purchasing":
let cid = client1.upload(byteutils.toHex(data)).get
let id = client1.requestStorage(
cid,
duration = 100.u256,
duration = 100.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
expiry = 30,
expiry = 30.uint64,
collateralPerByte = 1.u256,
nodes = 3,
tolerance = 1,
@ -49,10 +49,10 @@ twonodessuite "Purchasing":
let request = client1.getPurchase(id).get.request.get
check request.content.cid.data.buffer.len > 0
check request.ask.duration == 100.u256
check request.ask.duration == 100.uint64
check request.ask.pricePerBytePerSecond == 1.u256
check request.ask.proofProbability == 3.u256
check request.expiry == 30
check request.expiry == 30.uint64
check request.ask.collateralPerByte == 1.u256
check request.ask.slots == 3'u64
check request.ask.maxSlotLoss == 1'u64
@ -78,10 +78,10 @@ twonodessuite "Purchasing":
let cid = client1.upload(data).get
let id = client1.requestStorage(
cid,
duration = 10 * 60.u256,
duration = 10 * 60.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
expiry = 5 * 60,
expiry = 5 * 60.uint64,
collateralPerByte = 1.u256,
nodes = 3.uint,
tolerance = 1.uint,
@ -93,10 +93,10 @@ twonodessuite "Purchasing":
check eventually(client1.purchaseStateIs(id, "submitted"), timeout = 3 * 60 * 1000)
let request = client1.getPurchase(id).get.request.get
check request.ask.duration == (10 * 60).u256
check request.ask.duration == (10 * 60).uint64
check request.ask.pricePerBytePerSecond == 1.u256
check request.ask.proofProbability == 3.u256
check request.expiry == (5 * 60).u256
check request.expiry == (5 * 60).uint64
check request.ask.collateralPerByte == 1.u256
check request.ask.slots == 3'u64
check request.ask.maxSlotLoss == 1'u64
@ -107,7 +107,7 @@ twonodessuite "Purchasing":
let responseMissing = client1.requestStorageRaw(
cid,
duration = 1.u256,
duration = 1.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
collateralPerByte = 1.u256,
@ -117,11 +117,11 @@ twonodessuite "Purchasing":
let responseBefore = client1.requestStorageRaw(
cid,
duration = 10.u256,
duration = 10.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
collateralPerByte = 1.u256,
expiry = 10,
expiry = 10.uint64,
)
check responseBefore.status == "400 Bad Request"
check "Expiry needs value bigger then zero and smaller then the request's duration" in

View File

@ -25,12 +25,12 @@ twonodessuite "REST API":
test "node shows used and available space", twoNodesConfig:
discard client1.upload("some file contents").get
let totalSize = 12.u256
let totalSize = 12.uint64
let minPricePerBytePerSecond = 1.u256
let totalCollateral = totalSize * minPricePerBytePerSecond
let totalCollateral = totalSize.u256 * minPricePerBytePerSecond
discard client1.postAvailability(
totalSize = totalSize,
duration = 2.u256,
duration = 2.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = totalCollateral,
).get
@ -56,11 +56,11 @@ twonodessuite "REST API":
let cid = client1.upload("some file contents").get
let response = client1.requestStorageRaw(
cid,
duration = 10.u256,
duration = 10.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
collateralPerByte = 1.u256,
expiry = 9,
expiry = 9.uint64,
)
check:
@ -74,11 +74,11 @@ twonodessuite "REST API":
let cid = client1.upload(data).get
let response = client1.requestStorageRaw(
cid,
duration = 10.u256,
duration = 10.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
collateralPerByte = 1.u256,
expiry = 9,
expiry = 9.uint64,
)
check:
@ -87,10 +87,10 @@ twonodessuite "REST API":
test "request storage fails if tolerance is zero", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get
let duration = 100.u256
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 0
@ -106,7 +106,7 @@ twonodessuite "REST API":
test "request storage fails if duration exceeds limit", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get
let duration = (31 * 24 * 60 * 60).u256
let duration = (31 * 24 * 60 * 60).uint64
# 31 days TODO: this should not be hardcoded, but waits for https://github.com/codex-storage/nim-codex/issues/1056
let proofProbability = 3.u256
let expiry = 30.uint
@ -126,10 +126,10 @@ twonodessuite "REST API":
test "request storage fails if nodes and tolerance aren't correct", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get
let duration = 100.u256
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint
let expiry = 30.uint64
let collateralPerByte = 1.u256
let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)]
@ -149,10 +149,10 @@ twonodessuite "REST API":
twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get
let duration = 100.u256
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint
let expiry = 30.uint64
let collateralPerByte = 1.u256
let ecParams = @[(0, 1), (1, 2), (2, 3)]
@ -176,10 +176,10 @@ twonodessuite "REST API":
fmt"({minBlocks=}, {nodes=}, {tolerance=})", twoNodesConfig:
let data = await RandomChunker.example(blocks = minBlocks)
let cid = client1.upload(data).get
let duration = 100.u256
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint
let expiry = 30.uint64
let collateralPerByte = 1.u256
var responseBefore = client1.requestStorageRaw(

View File

@ -31,14 +31,14 @@ multinodesuite "Sales":
test "node handles new storage availability", salesConfig:
let availability1 = host.postAvailability(
totalSize = 1.u256,
duration = 2.u256,
totalSize = 1.uint64,
duration = 2.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 4.u256,
).get
let availability2 = host.postAvailability(
totalSize = 4.u256,
duration = 5.u256,
totalSize = 4.uint64,
duration = 5.uint64,
minPricePerBytePerSecond = 6.u256,
totalCollateral = 7.u256,
).get
@ -46,8 +46,8 @@ multinodesuite "Sales":
test "node lists storage that is for sale", salesConfig:
let availability = host.postAvailability(
totalSize = 1.u256,
duration = 2.u256,
totalSize = 1.uint64,
duration = 2.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 4.u256,
).get
@ -56,7 +56,7 @@ multinodesuite "Sales":
test "updating non-existing availability", salesConfig:
let nonExistingResponse = host.patchAvailabilityRaw(
AvailabilityId.example,
duration = 100.u256.some,
duration = 100.uint64.some,
minPricePerBytePerSecond = 2.u256.some,
totalCollateral = 200.u256.some,
)
@ -64,60 +64,60 @@ multinodesuite "Sales":
test "updating availability", salesConfig:
let availability = host.postAvailability(
totalSize = 140000.u256,
duration = 200.u256,
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
).get
host.patchAvailability(
availability.id,
duration = 100.u256.some,
duration = 100.uint64.some,
minPricePerBytePerSecond = 2.u256.some,
totalCollateral = 200.u256.some,
)
let updatedAvailability = (host.getAvailabilities().get).findItem(availability).get
check updatedAvailability.duration == 100
check updatedAvailability.duration == 100.uint64
check updatedAvailability.minPricePerBytePerSecond == 2
check updatedAvailability.totalCollateral == 200
check updatedAvailability.totalSize == 140000
check updatedAvailability.freeSize == 140000
check updatedAvailability.totalSize == 140000.uint64
check updatedAvailability.freeSize == 140000.uint64
test "updating availability - freeSize is not allowed to be changed", salesConfig:
let availability = host.postAvailability(
totalSize = 140000.u256,
duration = 200.u256,
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
).get
let freeSizeResponse =
host.patchAvailabilityRaw(availability.id, freeSize = 110000.u256.some)
host.patchAvailabilityRaw(availability.id, freeSize = 110000.uint64.some)
check freeSizeResponse.status == "400 Bad Request"
check "not allowed" in freeSizeResponse.body
test "updating availability - updating totalSize", salesConfig:
let availability = host.postAvailability(
totalSize = 140000.u256,
duration = 200.u256,
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
).get
host.patchAvailability(availability.id, totalSize = 100000.u256.some)
host.patchAvailability(availability.id, totalSize = 100000.uint64.some)
let updatedAvailability = (host.getAvailabilities().get).findItem(availability).get
check updatedAvailability.totalSize == 100000
check updatedAvailability.freeSize == 100000
test "updating availability - updating totalSize does not allow bellow utilized",
salesConfig:
let originalSize = 0xFFFFFF.u256
let originalSize = 0xFFFFFF.uint64
let data = await RandomChunker.example(blocks = 8)
let minPricePerBytePerSecond = 3.u256
let collateralPerByte = 1.u256
let totalCollateral = originalSize * collateralPerByte
let totalCollateral = originalSize.u256 * collateralPerByte
let availability = host.postAvailability(
totalSize = originalSize,
duration = 20 * 60.u256,
duration = 20 * 60.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = totalCollateral,
).get
@ -126,10 +126,10 @@ multinodesuite "Sales":
let cid = client.upload(data).get
let id = client.requestStorage(
cid,
duration = 20 * 60.u256,
duration = 20 * 60.uint64,
pricePerBytePerSecond = minPricePerBytePerSecond,
proofProbability = 3.u256,
expiry = 10 * 60,
expiry = (10 * 60).uint64,
collateralPerByte = collateralPerByte,
nodes = 3,
tolerance = 1,
@ -140,9 +140,8 @@ multinodesuite "Sales":
check updatedAvailability.totalSize != updatedAvailability.freeSize
let utilizedSize = updatedAvailability.totalSize - updatedAvailability.freeSize
let totalSizeResponse = host.patchAvailabilityRaw(
availability.id, totalSize = (utilizedSize - 1.u256).some
)
let totalSizeResponse =
host.patchAvailabilityRaw(availability.id, totalSize = (utilizedSize - 1).some)
check totalSizeResponse.status == "400 Bad Request"
check "totalSize must be larger then current totalSize" in totalSizeResponse.body

View File

@ -37,7 +37,7 @@ marketplacesuite "Validation":
const blocks = 8
const ecNodes = 3
const ecTolerance = 1
const proofProbability = 1
const proofProbability = 1.u256
const collateralPerByte = 1.u256
const minPricePerBytePerSecond = 1.u256
@ -100,7 +100,10 @@ marketplacesuite "Validation":
let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
createAvailabilities(
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
datasetSize.truncate(uint64),
duration,
collateralPerByte,
minPricePerBytePerSecond,
)
let cid = client0.upload(data).get
@ -167,7 +170,10 @@ marketplacesuite "Validation":
let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
createAvailabilities(
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
datasetSize.truncate(uint64),
duration,
collateralPerByte,
minPricePerBytePerSecond,
)
let cid = client0.upload(data).get

@ -1 +1 @@
Subproject commit ff82c26b3669b52a09280c634141dace7f04659a
Subproject commit 32a6c13def1c1505765e9e0dc465117fba98c161