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) let asUint = uint64.fromBytes(bytes)
cast[int64](asUint) cast[int64](asUint)
proc toSecondsSince1970*(num: uint64): SecondsSince1970 =
cast[int64](num)
proc toSecondsSince1970*(bigint: UInt256): SecondsSince1970 = proc toSecondsSince1970*(bigint: UInt256): SecondsSince1970 =
bigint.truncate(int64) bigint.truncate(int64)

View File

@ -11,7 +11,7 @@ type
collateral*: CollateralConfig collateral*: CollateralConfig
proofs*: ProofConfig proofs*: ProofConfig
reservations*: SlotReservationsConfig reservations*: SlotReservationsConfig
requestDurationLimit*: UInt256 requestDurationLimit*: uint64
CollateralConfig* = object CollateralConfig* = object
repairRewardPercentage*: uint8 repairRewardPercentage*: uint8
@ -22,14 +22,14 @@ type
# percentage of the slashed amount going to the validators # percentage of the slashed amount going to the validators
ProofConfig* = object ProofConfig* = object
period*: UInt256 # proofs requirements are calculated per period (in seconds) period*: uint64 # proofs requirements are calculated per period (in seconds)
timeout*: UInt256 # mark proofs as missing before the timeout (in seconds) timeout*: uint64 # mark proofs as missing before the timeout (in seconds)
downtime*: uint8 # ignore this much recent blocks for proof requirements 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 zkeyHash*: string # hash of the zkey file which is linked to the verifier
# Ensures the pointer does not remain in downtime for many consecutive # Ensures the pointer does not remain in downtime for many consecutive
# periods. For each period increase, move the pointer `pointerProduct` # periods. For each period increase, move the pointer `pointerProduct`
# blocks. Should be a prime number to ensure there are no cycles. # blocks. Should be a prime number to ensure there are no cycles.
downtimeProduct*: uint8
SlotReservationsConfig* = object SlotReservationsConfig* = object
maxReservations*: uint8 maxReservations*: uint8
@ -39,8 +39,8 @@ func fromTuple(_: type ProofConfig, tupl: tuple): ProofConfig =
period: tupl[0], period: tupl[0],
timeout: tupl[1], timeout: tupl[1],
downtime: tupl[2], downtime: tupl[2],
zkeyHash: tupl[3], downtimeProduct: tupl[3],
downtimeProduct: tupl[4], zkeyHash: tupl[4],
) )
func fromTuple(_: type SlotReservationsConfig, tupl: tuple): SlotReservationsConfig = 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 let period = config.proofs.period
return Periodicity(seconds: period) return Periodicity(seconds: period)
method proofTimeout*(market: OnChainMarket): Future[UInt256] {.async.} = method proofTimeout*(market: OnChainMarket): Future[uint64] {.async.} =
convertEthersError: convertEthersError:
let config = await market.config() let config = await market.config()
return config.proofs.timeout return config.proofs.timeout
@ -94,7 +94,7 @@ method repairRewardPercentage*(market: OnChainMarket): Future[uint8] {.async.} =
let config = await market.config() let config = await market.config()
return config.collateral.repairRewardPercentage return config.collateral.repairRewardPercentage
method requestDurationLimit*(market: OnChainMarket): Future[UInt256] {.async.} = method requestDurationLimit*(market: OnChainMarket): Future[uint64] {.async.} =
convertEthersError: convertEthersError:
let config = await market.config() let config = await market.config()
return config.requestDurationLimit return config.requestDurationLimit
@ -170,7 +170,7 @@ method requestExpiresAt*(
return await market.contract.requestExpiry(id) return await market.contract.requestExpiry(id)
method getHost( method getHost(
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256 market: OnChainMarket, requestId: RequestId, slotIndex: uint64
): Future[?Address] {.async.} = ): Future[?Address] {.async.} =
convertEthersError: convertEthersError:
let slotId = slotId(requestId, slotIndex) let slotId = slotId(requestId, slotIndex)
@ -196,7 +196,7 @@ method getActiveSlot*(market: OnChainMarket, slotId: SlotId): Future[?Slot] {.as
method fillSlot( method fillSlot(
market: OnChainMarket, market: OnChainMarket,
requestId: RequestId, requestId: RequestId,
slotIndex: UInt256, slotIndex: uint64,
proof: Groth16Proof, proof: Groth16Proof,
collateral: UInt256, collateral: UInt256,
) {.async.} = ) {.async.} =
@ -280,7 +280,7 @@ method canProofBeMarkedAsMissing*(
return false return false
method reserveSlot*( method reserveSlot*(
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256 market: OnChainMarket, requestId: RequestId, slotIndex: uint64
) {.async.} = ) {.async.} =
convertEthersError: convertEthersError:
discard await market.contract discard await market.contract
@ -293,7 +293,7 @@ method reserveSlot*(
.confirm(1) .confirm(1)
method canReserveSlot*( method canReserveSlot*(
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256 market: OnChainMarket, requestId: RequestId, slotIndex: uint64
): Future[bool] {.async.} = ): Future[bool] {.async.} =
convertEthersError: convertEthersError:
return await market.contract.canReserveSlot(requestId, slotIndex) return await market.contract.canReserveSlot(requestId, slotIndex)
@ -329,10 +329,10 @@ method subscribeSlotFilled*(
method subscribeSlotFilled*( method subscribeSlotFilled*(
market: OnChainMarket, market: OnChainMarket,
requestId: RequestId, requestId: RequestId,
slotIndex: UInt256, slotIndex: uint64,
callback: OnSlotFilled, callback: OnSlotFilled,
): Future[MarketSubscription] {.async.} = ): Future[MarketSubscription] {.async.} =
proc onSlotFilled(eventRequestId: RequestId, eventSlotIndex: UInt256) = proc onSlotFilled(eventRequestId: RequestId, eventSlotIndex: uint64) =
if eventRequestId == requestId and eventSlotIndex == slotIndex: if eventRequestId == requestId and eventSlotIndex == slotIndex:
callback(requestId, slotIndex) callback(requestId, slotIndex)

View File

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

View File

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

View File

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

View File

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

View File

@ -2,10 +2,10 @@ import pkg/stint
type type
Periodicity* = object Periodicity* = object
seconds*: UInt256 seconds*: uint64
Period* = UInt256 Period* = uint64
Timestamp* = UInt256 Timestamp* = uint64
func periodOf*(periodicity: Periodicity, timestamp: Timestamp): Period = func periodOf*(periodicity: Periodicity, timestamp: Timestamp): Period =
timestamp div periodicity.seconds 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 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 return
RestApiResponse.error(Http422, "Not enough storage quota", headers = headers) RestApiResponse.error(Http422, "Not enough storage quota", headers = headers)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -20,7 +20,7 @@ when codex_enable_proof_failures:
failEveryNProofs*: int failEveryNProofs*: int
proofCount: 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 error "Submitting invalid proof failed", period, slotId, msg = error.msgDetail
method prove*( method prove*(

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -3,6 +3,6 @@ import ../../helpers/mockclock
proc advanceToNextPeriod*(clock: MockClock, market: Market) {.async.} = proc advanceToNextPeriod*(clock: MockClock, market: Market) {.async.} =
let periodicity = await market.periodicity() let periodicity = await market.periodicity()
let period = periodicity.periodOf(clock.now().u256) let period = periodicity.periodOf(clock.now().Timestamp)
let periodEnd = periodicity.periodEnd(period) 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'": asyncchecksuite "sales state 'cancelled'":
let request = StorageRequest.example let request = StorageRequest.example
let slotIndex = (request.ask.slots div 2).u256 let slotIndex = request.ask.slots div 2
let clock = MockClock.new() let clock = MockClock.new()
let currentCollateral = UInt256.example let currentCollateral = UInt256.example

View File

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

View File

@ -14,7 +14,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'errored'": asyncchecksuite "sales state 'errored'":
let request = StorageRequest.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 market = MockMarket.new()
let clock = MockClock.new() let clock = MockClock.new()

View File

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

View File

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

View File

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

View File

@ -14,7 +14,7 @@ import ../../helpers/mockclock
asyncchecksuite "sales state 'ignored'": asyncchecksuite "sales state 'ignored'":
let request = StorageRequest.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 market = MockMarket.new()
let clock = MockClock.new() let clock = MockClock.new()

View File

@ -20,7 +20,7 @@ import ../helpers/periods
asyncchecksuite "sales state 'initialproving'": asyncchecksuite "sales state 'initialproving'":
let proof = Groth16Proof.example let proof = Groth16Proof.example
let request = StorageRequest.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 market = MockMarket.new()
let clock = MockClock.new() let clock = MockClock.new()

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -16,7 +16,7 @@ import ../../helpers
checksuite "sales state 'unknown'": checksuite "sales state 'unknown'":
let request = StorageRequest.example 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) let slotId = slotId(request.id, slotIndex)
var market: MockMarket var market: MockMarket

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,18 +11,18 @@ twonodessuite "Purchasing":
let cid = client1.upload(data).get let cid = client1.upload(data).get
let id1 = client1.requestStorage( let id1 = client1.requestStorage(
cid, cid,
duration = 100.u256, duration = 100.uint64,
pricePerBytePerSecond = 1.u256, pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
expiry = 10, expiry = 10.uint64,
collateralPerByte = 1.u256, collateralPerByte = 1.u256,
).get ).get
let id2 = client1.requestStorage( let id2 = client1.requestStorage(
cid, cid,
duration = 400.u256, duration = 400.uint64,
pricePerBytePerSecond = 2.u256, pricePerBytePerSecond = 2.u256,
proofProbability = 6.u256, proofProbability = 6.u256,
expiry = 10, expiry = 10.uint64,
collateralPerByte = 2.u256, collateralPerByte = 2.u256,
).get ).get
check id1 != id2 check id1 != id2
@ -37,10 +37,10 @@ twonodessuite "Purchasing":
let cid = client1.upload(byteutils.toHex(data)).get let cid = client1.upload(byteutils.toHex(data)).get
let id = client1.requestStorage( let id = client1.requestStorage(
cid, cid,
duration = 100.u256, duration = 100.uint64,
pricePerBytePerSecond = 1.u256, pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
expiry = 30, expiry = 30.uint64,
collateralPerByte = 1.u256, collateralPerByte = 1.u256,
nodes = 3, nodes = 3,
tolerance = 1, tolerance = 1,
@ -49,10 +49,10 @@ twonodessuite "Purchasing":
let request = client1.getPurchase(id).get.request.get let request = client1.getPurchase(id).get.request.get
check request.content.cid.data.buffer.len > 0 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.pricePerBytePerSecond == 1.u256
check request.ask.proofProbability == 3.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.collateralPerByte == 1.u256
check request.ask.slots == 3'u64 check request.ask.slots == 3'u64
check request.ask.maxSlotLoss == 1'u64 check request.ask.maxSlotLoss == 1'u64
@ -78,10 +78,10 @@ twonodessuite "Purchasing":
let cid = client1.upload(data).get let cid = client1.upload(data).get
let id = client1.requestStorage( let id = client1.requestStorage(
cid, cid,
duration = 10 * 60.u256, duration = 10 * 60.uint64,
pricePerBytePerSecond = 1.u256, pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
expiry = 5 * 60, expiry = 5 * 60.uint64,
collateralPerByte = 1.u256, collateralPerByte = 1.u256,
nodes = 3.uint, nodes = 3.uint,
tolerance = 1.uint, tolerance = 1.uint,
@ -93,10 +93,10 @@ twonodessuite "Purchasing":
check eventually(client1.purchaseStateIs(id, "submitted"), timeout = 3 * 60 * 1000) check eventually(client1.purchaseStateIs(id, "submitted"), timeout = 3 * 60 * 1000)
let request = client1.getPurchase(id).get.request.get 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.pricePerBytePerSecond == 1.u256
check request.ask.proofProbability == 3.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.collateralPerByte == 1.u256
check request.ask.slots == 3'u64 check request.ask.slots == 3'u64
check request.ask.maxSlotLoss == 1'u64 check request.ask.maxSlotLoss == 1'u64
@ -107,7 +107,7 @@ twonodessuite "Purchasing":
let responseMissing = client1.requestStorageRaw( let responseMissing = client1.requestStorageRaw(
cid, cid,
duration = 1.u256, duration = 1.uint64,
pricePerBytePerSecond = 1.u256, pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
collateralPerByte = 1.u256, collateralPerByte = 1.u256,
@ -117,11 +117,11 @@ twonodessuite "Purchasing":
let responseBefore = client1.requestStorageRaw( let responseBefore = client1.requestStorageRaw(
cid, cid,
duration = 10.u256, duration = 10.uint64,
pricePerBytePerSecond = 1.u256, pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
collateralPerByte = 1.u256, collateralPerByte = 1.u256,
expiry = 10, expiry = 10.uint64,
) )
check responseBefore.status == "400 Bad Request" check responseBefore.status == "400 Bad Request"
check "Expiry needs value bigger then zero and smaller then the request's duration" in 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: test "node shows used and available space", twoNodesConfig:
discard client1.upload("some file contents").get discard client1.upload("some file contents").get
let totalSize = 12.u256 let totalSize = 12.uint64
let minPricePerBytePerSecond = 1.u256 let minPricePerBytePerSecond = 1.u256
let totalCollateral = totalSize * minPricePerBytePerSecond let totalCollateral = totalSize.u256 * minPricePerBytePerSecond
discard client1.postAvailability( discard client1.postAvailability(
totalSize = totalSize, totalSize = totalSize,
duration = 2.u256, duration = 2.uint64,
minPricePerBytePerSecond = minPricePerBytePerSecond, minPricePerBytePerSecond = minPricePerBytePerSecond,
totalCollateral = totalCollateral, totalCollateral = totalCollateral,
).get ).get
@ -56,11 +56,11 @@ twonodessuite "REST API":
let cid = client1.upload("some file contents").get let cid = client1.upload("some file contents").get
let response = client1.requestStorageRaw( let response = client1.requestStorageRaw(
cid, cid,
duration = 10.u256, duration = 10.uint64,
pricePerBytePerSecond = 1.u256, pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
collateralPerByte = 1.u256, collateralPerByte = 1.u256,
expiry = 9, expiry = 9.uint64,
) )
check: check:
@ -74,11 +74,11 @@ twonodessuite "REST API":
let cid = client1.upload(data).get let cid = client1.upload(data).get
let response = client1.requestStorageRaw( let response = client1.requestStorageRaw(
cid, cid,
duration = 10.u256, duration = 10.uint64,
pricePerBytePerSecond = 1.u256, pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
collateralPerByte = 1.u256, collateralPerByte = 1.u256,
expiry = 9, expiry = 9.uint64,
) )
check: check:
@ -87,10 +87,10 @@ twonodessuite "REST API":
test "request storage fails if tolerance is zero", twoNodesConfig: test "request storage fails if tolerance is zero", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2) let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get let cid = client1.upload(data).get
let duration = 100.u256 let duration = 100.uint64
let pricePerBytePerSecond = 1.u256 let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256 let proofProbability = 3.u256
let expiry = 30.uint let expiry = 30.uint64
let collateralPerByte = 1.u256 let collateralPerByte = 1.u256
let nodes = 3 let nodes = 3
let tolerance = 0 let tolerance = 0
@ -106,7 +106,7 @@ twonodessuite "REST API":
test "request storage fails if duration exceeds limit", twoNodesConfig: test "request storage fails if duration exceeds limit", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2) let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get 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 # 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 proofProbability = 3.u256
let expiry = 30.uint let expiry = 30.uint
@ -126,10 +126,10 @@ twonodessuite "REST API":
test "request storage fails if nodes and tolerance aren't correct", twoNodesConfig: test "request storage fails if nodes and tolerance aren't correct", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2) let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get let cid = client1.upload(data).get
let duration = 100.u256 let duration = 100.uint64
let pricePerBytePerSecond = 1.u256 let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256 let proofProbability = 3.u256
let expiry = 30.uint let expiry = 30.uint64
let collateralPerByte = 1.u256 let collateralPerByte = 1.u256
let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)] let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)]
@ -149,10 +149,10 @@ twonodessuite "REST API":
twoNodesConfig: twoNodesConfig:
let data = await RandomChunker.example(blocks = 2) let data = await RandomChunker.example(blocks = 2)
let cid = client1.upload(data).get let cid = client1.upload(data).get
let duration = 100.u256 let duration = 100.uint64
let pricePerBytePerSecond = 1.u256 let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256 let proofProbability = 3.u256
let expiry = 30.uint let expiry = 30.uint64
let collateralPerByte = 1.u256 let collateralPerByte = 1.u256
let ecParams = @[(0, 1), (1, 2), (2, 3)] let ecParams = @[(0, 1), (1, 2), (2, 3)]
@ -176,10 +176,10 @@ twonodessuite "REST API":
fmt"({minBlocks=}, {nodes=}, {tolerance=})", twoNodesConfig: fmt"({minBlocks=}, {nodes=}, {tolerance=})", twoNodesConfig:
let data = await RandomChunker.example(blocks = minBlocks) let data = await RandomChunker.example(blocks = minBlocks)
let cid = client1.upload(data).get let cid = client1.upload(data).get
let duration = 100.u256 let duration = 100.uint64
let pricePerBytePerSecond = 1.u256 let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256 let proofProbability = 3.u256
let expiry = 30.uint let expiry = 30.uint64
let collateralPerByte = 1.u256 let collateralPerByte = 1.u256
var responseBefore = client1.requestStorageRaw( var responseBefore = client1.requestStorageRaw(

View File

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

View File

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

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