mirror of
https://github.com/logos-storage/logos-storage-nim.git
synced 2026-01-02 13:33:10 +00:00
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:
parent
04327a3986
commit
44981d24d0
@ -40,5 +40,8 @@ proc toSecondsSince1970*(bytes: seq[byte]): SecondsSince1970 =
|
||||
let asUint = uint64.fromBytes(bytes)
|
||||
cast[int64](asUint)
|
||||
|
||||
proc toSecondsSince1970*(num: uint64): SecondsSince1970 =
|
||||
cast[int64](num)
|
||||
|
||||
proc toSecondsSince1970*(bigint: UInt256): SecondsSince1970 =
|
||||
bigint.truncate(int64)
|
||||
|
||||
@ -11,7 +11,7 @@ type
|
||||
collateral*: CollateralConfig
|
||||
proofs*: ProofConfig
|
||||
reservations*: SlotReservationsConfig
|
||||
requestDurationLimit*: UInt256
|
||||
requestDurationLimit*: uint64
|
||||
|
||||
CollateralConfig* = object
|
||||
repairRewardPercentage*: uint8
|
||||
@ -22,14 +22,14 @@ type
|
||||
# percentage of the slashed amount going to the validators
|
||||
|
||||
ProofConfig* = object
|
||||
period*: UInt256 # proofs requirements are calculated per period (in seconds)
|
||||
timeout*: UInt256 # mark proofs as missing before the timeout (in seconds)
|
||||
period*: uint64 # proofs requirements are calculated per period (in seconds)
|
||||
timeout*: uint64 # mark proofs as missing before the timeout (in seconds)
|
||||
downtime*: uint8 # ignore this much recent blocks for proof requirements
|
||||
downtimeProduct*: uint8
|
||||
zkeyHash*: string # hash of the zkey file which is linked to the verifier
|
||||
# Ensures the pointer does not remain in downtime for many consecutive
|
||||
# periods. For each period increase, move the pointer `pointerProduct`
|
||||
# blocks. Should be a prime number to ensure there are no cycles.
|
||||
downtimeProduct*: uint8
|
||||
|
||||
SlotReservationsConfig* = object
|
||||
maxReservations*: uint8
|
||||
@ -39,8 +39,8 @@ func fromTuple(_: type ProofConfig, tupl: tuple): ProofConfig =
|
||||
period: tupl[0],
|
||||
timeout: tupl[1],
|
||||
downtime: tupl[2],
|
||||
zkeyHash: tupl[3],
|
||||
downtimeProduct: tupl[4],
|
||||
downtimeProduct: tupl[3],
|
||||
zkeyHash: tupl[4],
|
||||
)
|
||||
|
||||
func fromTuple(_: type SlotReservationsConfig, tupl: tuple): SlotReservationsConfig =
|
||||
|
||||
@ -84,7 +84,7 @@ method periodicity*(market: OnChainMarket): Future[Periodicity] {.async.} =
|
||||
let period = config.proofs.period
|
||||
return Periodicity(seconds: period)
|
||||
|
||||
method proofTimeout*(market: OnChainMarket): Future[UInt256] {.async.} =
|
||||
method proofTimeout*(market: OnChainMarket): Future[uint64] {.async.} =
|
||||
convertEthersError:
|
||||
let config = await market.config()
|
||||
return config.proofs.timeout
|
||||
@ -94,7 +94,7 @@ method repairRewardPercentage*(market: OnChainMarket): Future[uint8] {.async.} =
|
||||
let config = await market.config()
|
||||
return config.collateral.repairRewardPercentage
|
||||
|
||||
method requestDurationLimit*(market: OnChainMarket): Future[UInt256] {.async.} =
|
||||
method requestDurationLimit*(market: OnChainMarket): Future[uint64] {.async.} =
|
||||
convertEthersError:
|
||||
let config = await market.config()
|
||||
return config.requestDurationLimit
|
||||
@ -170,7 +170,7 @@ method requestExpiresAt*(
|
||||
return await market.contract.requestExpiry(id)
|
||||
|
||||
method getHost(
|
||||
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256
|
||||
market: OnChainMarket, requestId: RequestId, slotIndex: uint64
|
||||
): Future[?Address] {.async.} =
|
||||
convertEthersError:
|
||||
let slotId = slotId(requestId, slotIndex)
|
||||
@ -196,7 +196,7 @@ method getActiveSlot*(market: OnChainMarket, slotId: SlotId): Future[?Slot] {.as
|
||||
method fillSlot(
|
||||
market: OnChainMarket,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
proof: Groth16Proof,
|
||||
collateral: UInt256,
|
||||
) {.async.} =
|
||||
@ -280,7 +280,7 @@ method canProofBeMarkedAsMissing*(
|
||||
return false
|
||||
|
||||
method reserveSlot*(
|
||||
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256
|
||||
market: OnChainMarket, requestId: RequestId, slotIndex: uint64
|
||||
) {.async.} =
|
||||
convertEthersError:
|
||||
discard await market.contract
|
||||
@ -293,7 +293,7 @@ method reserveSlot*(
|
||||
.confirm(1)
|
||||
|
||||
method canReserveSlot*(
|
||||
market: OnChainMarket, requestId: RequestId, slotIndex: UInt256
|
||||
market: OnChainMarket, requestId: RequestId, slotIndex: uint64
|
||||
): Future[bool] {.async.} =
|
||||
convertEthersError:
|
||||
return await market.contract.canReserveSlot(requestId, slotIndex)
|
||||
@ -329,10 +329,10 @@ method subscribeSlotFilled*(
|
||||
method subscribeSlotFilled*(
|
||||
market: OnChainMarket,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
callback: OnSlotFilled,
|
||||
): Future[MarketSubscription] {.async.} =
|
||||
proc onSlotFilled(eventRequestId: RequestId, eventSlotIndex: UInt256) =
|
||||
proc onSlotFilled(eventRequestId: RequestId, eventSlotIndex: uint64) =
|
||||
if eventRequestId == requestId and eventSlotIndex == slotIndex:
|
||||
callback(requestId, slotIndex)
|
||||
|
||||
|
||||
@ -60,10 +60,6 @@ proc currentCollateral*(
|
||||
marketplace: Marketplace, id: SlotId
|
||||
): UInt256 {.contract, view.}
|
||||
|
||||
proc slashMisses*(marketplace: Marketplace): UInt256 {.contract, view.}
|
||||
proc slashPercentage*(marketplace: Marketplace): UInt256 {.contract, view.}
|
||||
proc minCollateralThreshold*(marketplace: Marketplace): UInt256 {.contract, view.}
|
||||
|
||||
proc requestStorage*(
|
||||
marketplace: Marketplace, request: StorageRequest
|
||||
): Confirmable {.
|
||||
@ -76,10 +72,7 @@ proc requestStorage*(
|
||||
.}
|
||||
|
||||
proc fillSlot*(
|
||||
marketplace: Marketplace,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
proof: Groth16Proof,
|
||||
marketplace: Marketplace, requestId: RequestId, slotIndex: uint64, proof: Groth16Proof
|
||||
): Confirmable {.
|
||||
contract,
|
||||
errors: [
|
||||
@ -155,9 +148,6 @@ proc requestExpiry*(
|
||||
marketplace: Marketplace, requestId: RequestId
|
||||
): SecondsSince1970 {.contract, view.}
|
||||
|
||||
proc proofTimeout*(marketplace: Marketplace): UInt256 {.contract, view.}
|
||||
|
||||
proc proofEnd*(marketplace: Marketplace, id: SlotId): UInt256 {.contract, view.}
|
||||
proc missingProofs*(marketplace: Marketplace, id: SlotId): UInt256 {.contract, view.}
|
||||
proc isProofRequired*(marketplace: Marketplace, id: SlotId): bool {.contract, view.}
|
||||
proc willProofBeRequired*(marketplace: Marketplace, id: SlotId): bool {.contract, view.}
|
||||
@ -176,7 +166,7 @@ proc submitProof*(
|
||||
.}
|
||||
|
||||
proc markProofAsMissing*(
|
||||
marketplace: Marketplace, id: SlotId, period: UInt256
|
||||
marketplace: Marketplace, id: SlotId, period: uint64
|
||||
): Confirmable {.
|
||||
contract,
|
||||
errors: [
|
||||
@ -187,9 +177,9 @@ proc markProofAsMissing*(
|
||||
.}
|
||||
|
||||
proc reserveSlot*(
|
||||
marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256
|
||||
marketplace: Marketplace, requestId: RequestId, slotIndex: uint64
|
||||
): Confirmable {.contract.}
|
||||
|
||||
proc canReserveSlot*(
|
||||
marketplace: Marketplace, requestId: RequestId, slotIndex: UInt256
|
||||
marketplace: Marketplace, requestId: RequestId, slotIndex: uint64
|
||||
): bool {.contract, view.}
|
||||
|
||||
@ -9,6 +9,7 @@ import pkg/stew/byteutils
|
||||
import pkg/libp2p/[cid, multicodec]
|
||||
import ../logutils
|
||||
import ../utils/json
|
||||
import ../clock
|
||||
from ../errors import mapFailure
|
||||
|
||||
export contractabi
|
||||
@ -18,16 +19,16 @@ type
|
||||
client* {.serialize.}: Address
|
||||
ask* {.serialize.}: StorageAsk
|
||||
content* {.serialize.}: StorageContent
|
||||
expiry* {.serialize.}: UInt256
|
||||
expiry* {.serialize.}: uint64
|
||||
nonce*: Nonce
|
||||
|
||||
StorageAsk* = object
|
||||
slots* {.serialize.}: uint64
|
||||
slotSize* {.serialize.}: UInt256
|
||||
duration* {.serialize.}: UInt256
|
||||
proofProbability* {.serialize.}: UInt256
|
||||
pricePerBytePerSecond* {.serialize.}: UInt256
|
||||
collateralPerByte* {.serialize.}: UInt256
|
||||
slots* {.serialize.}: uint64
|
||||
slotSize* {.serialize.}: uint64
|
||||
duration* {.serialize.}: uint64
|
||||
maxSlotLoss* {.serialize.}: uint64
|
||||
|
||||
StorageContent* = object
|
||||
@ -36,7 +37,7 @@ type
|
||||
|
||||
Slot* = object
|
||||
request* {.serialize.}: StorageRequest
|
||||
slotIndex* {.serialize.}: UInt256
|
||||
slotIndex* {.serialize.}: uint64
|
||||
|
||||
SlotId* = distinct array[32, byte]
|
||||
RequestId* = distinct array[32, byte]
|
||||
@ -110,12 +111,12 @@ func fromTuple(_: type Slot, tupl: tuple): Slot =
|
||||
|
||||
func fromTuple(_: type StorageAsk, tupl: tuple): StorageAsk =
|
||||
StorageAsk(
|
||||
slots: tupl[0],
|
||||
slotSize: tupl[1],
|
||||
duration: tupl[2],
|
||||
proofProbability: tupl[3],
|
||||
pricePerBytePerSecond: tupl[4],
|
||||
collateralPerByte: tupl[5],
|
||||
proofProbability: tupl[0],
|
||||
pricePerBytePerSecond: tupl[1],
|
||||
collateralPerByte: tupl[2],
|
||||
slots: tupl[3],
|
||||
slotSize: tupl[4],
|
||||
duration: tupl[5],
|
||||
maxSlotLoss: tupl[6],
|
||||
)
|
||||
|
||||
@ -177,21 +178,21 @@ func id*(request: StorageRequest): RequestId =
|
||||
let encoding = AbiEncoder.encode((request,))
|
||||
RequestId(keccak256.digest(encoding).data)
|
||||
|
||||
func slotId*(requestId: RequestId, slotIndex: UInt256): SlotId =
|
||||
func slotId*(requestId: RequestId, slotIndex: uint64): SlotId =
|
||||
let encoding = AbiEncoder.encode((requestId, slotIndex))
|
||||
SlotId(keccak256.digest(encoding).data)
|
||||
|
||||
func slotId*(request: StorageRequest, slotIndex: UInt256): SlotId =
|
||||
func slotId*(request: StorageRequest, slotIndex: uint64): SlotId =
|
||||
slotId(request.id, slotIndex)
|
||||
|
||||
func id*(slot: Slot): SlotId =
|
||||
slotId(slot.request, slot.slotIndex)
|
||||
|
||||
func pricePerSlotPerSecond*(ask: StorageAsk): UInt256 =
|
||||
ask.pricePerBytePerSecond * ask.slotSize
|
||||
ask.pricePerBytePerSecond * ask.slotSize.u256
|
||||
|
||||
func pricePerSlot*(ask: StorageAsk): UInt256 =
|
||||
ask.duration * ask.pricePerSlotPerSecond
|
||||
ask.duration.u256 * ask.pricePerSlotPerSecond
|
||||
|
||||
func totalPrice*(ask: StorageAsk): UInt256 =
|
||||
ask.slots.u256 * ask.pricePerSlot
|
||||
@ -200,7 +201,7 @@ func totalPrice*(request: StorageRequest): UInt256 =
|
||||
request.ask.totalPrice
|
||||
|
||||
func collateralPerSlot*(ask: StorageAsk): UInt256 =
|
||||
ask.collateralPerByte * ask.slotSize
|
||||
ask.collateralPerByte * ask.slotSize.u256
|
||||
|
||||
func size*(ask: StorageAsk): UInt256 =
|
||||
ask.slots.u256 * ask.slotSize
|
||||
func size*(ask: StorageAsk): uint64 =
|
||||
ask.slots * ask.slotSize
|
||||
|
||||
@ -20,13 +20,12 @@ type
|
||||
MarketError* = object of CodexError
|
||||
Subscription* = ref object of RootObj
|
||||
OnRequest* =
|
||||
proc(id: RequestId, ask: StorageAsk, expiry: UInt256) {.gcsafe, upraises: [].}
|
||||
proc(id: RequestId, ask: StorageAsk, expiry: uint64) {.gcsafe, upraises: [].}
|
||||
OnFulfillment* = proc(requestId: RequestId) {.gcsafe, upraises: [].}
|
||||
OnSlotFilled* =
|
||||
proc(requestId: RequestId, slotIndex: UInt256) {.gcsafe, upraises: [].}
|
||||
OnSlotFreed* = proc(requestId: RequestId, slotIndex: UInt256) {.gcsafe, upraises: [].}
|
||||
OnSlotFilled* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
|
||||
OnSlotFreed* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
|
||||
OnSlotReservationsFull* =
|
||||
proc(requestId: RequestId, slotIndex: UInt256) {.gcsafe, upraises: [].}
|
||||
proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
|
||||
OnRequestCancelled* = proc(requestId: RequestId) {.gcsafe, upraises: [].}
|
||||
OnRequestFailed* = proc(requestId: RequestId) {.gcsafe, upraises: [].}
|
||||
OnProofSubmitted* = proc(id: SlotId) {.gcsafe, upraises: [].}
|
||||
@ -37,19 +36,19 @@ type
|
||||
StorageRequested* = object of MarketplaceEvent
|
||||
requestId*: RequestId
|
||||
ask*: StorageAsk
|
||||
expiry*: UInt256
|
||||
expiry*: uint64
|
||||
|
||||
SlotFilled* = object of MarketplaceEvent
|
||||
requestId* {.indexed.}: RequestId
|
||||
slotIndex*: UInt256
|
||||
slotIndex*: uint64
|
||||
|
||||
SlotFreed* = object of MarketplaceEvent
|
||||
requestId* {.indexed.}: RequestId
|
||||
slotIndex*: UInt256
|
||||
slotIndex*: uint64
|
||||
|
||||
SlotReservationsFull* = object of MarketplaceEvent
|
||||
requestId* {.indexed.}: RequestId
|
||||
slotIndex*: UInt256
|
||||
slotIndex*: uint64
|
||||
|
||||
RequestFulfilled* = object of MarketplaceEvent
|
||||
requestId* {.indexed.}: RequestId
|
||||
@ -72,13 +71,13 @@ method getSigner*(market: Market): Future[Address] {.base, async.} =
|
||||
method periodicity*(market: Market): Future[Periodicity] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method proofTimeout*(market: Market): Future[UInt256] {.base, async.} =
|
||||
method proofTimeout*(market: Market): Future[uint64] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method repairRewardPercentage*(market: Market): Future[uint8] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method requestDurationLimit*(market: Market): Future[UInt256] {.base, async.} =
|
||||
method requestDurationLimit*(market: Market): Future[uint64] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method proofDowntime*(market: Market): Future[uint8] {.base, async.} =
|
||||
@ -125,7 +124,7 @@ method requestExpiresAt*(
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method getHost*(
|
||||
market: Market, requestId: RequestId, slotIndex: UInt256
|
||||
market: Market, requestId: RequestId, slotIndex: uint64
|
||||
): Future[?Address] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
@ -140,7 +139,7 @@ method getActiveSlot*(market: Market, slotId: SlotId): Future[?Slot] {.base, asy
|
||||
method fillSlot*(
|
||||
market: Market,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
proof: Groth16Proof,
|
||||
collateral: UInt256,
|
||||
) {.base, async.} =
|
||||
@ -180,12 +179,12 @@ method canProofBeMarkedAsMissing*(
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method reserveSlot*(
|
||||
market: Market, requestId: RequestId, slotIndex: UInt256
|
||||
market: Market, requestId: RequestId, slotIndex: uint64
|
||||
) {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method canReserveSlot*(
|
||||
market: Market, requestId: RequestId, slotIndex: UInt256
|
||||
market: Market, requestId: RequestId, slotIndex: uint64
|
||||
): Future[bool] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
@ -205,7 +204,7 @@ method subscribeSlotFilled*(
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method subscribeSlotFilled*(
|
||||
market: Market, requestId: RequestId, slotIndex: UInt256, callback: OnSlotFilled
|
||||
market: Market, requestId: RequestId, slotIndex: uint64, callback: OnSlotFilled
|
||||
): Future[Subscription] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
|
||||
@ -430,13 +430,13 @@ proc iterateManifests*(self: CodexNodeRef, onManifest: OnManifest) {.async.} =
|
||||
proc setupRequest(
|
||||
self: CodexNodeRef,
|
||||
cid: Cid,
|
||||
duration: UInt256,
|
||||
duration: uint64,
|
||||
proofProbability: UInt256,
|
||||
nodes: uint,
|
||||
tolerance: uint,
|
||||
pricePerBytePerSecond: UInt256,
|
||||
collateralPerByte: UInt256,
|
||||
expiry: UInt256,
|
||||
expiry: uint64,
|
||||
): Future[?!StorageRequest] {.async.} =
|
||||
## Setup slots for a given dataset
|
||||
##
|
||||
@ -494,7 +494,7 @@ proc setupRequest(
|
||||
request = StorageRequest(
|
||||
ask: StorageAsk(
|
||||
slots: verifiable.numSlots.uint64,
|
||||
slotSize: builder.slotBytes.uint.u256,
|
||||
slotSize: builder.slotBytes.uint64,
|
||||
duration: duration,
|
||||
proofProbability: proofProbability,
|
||||
pricePerBytePerSecond: pricePerBytePerSecond,
|
||||
@ -511,13 +511,13 @@ proc setupRequest(
|
||||
proc requestStorage*(
|
||||
self: CodexNodeRef,
|
||||
cid: Cid,
|
||||
duration: UInt256,
|
||||
duration: uint64,
|
||||
proofProbability: UInt256,
|
||||
nodes: uint,
|
||||
tolerance: uint,
|
||||
pricePerBytePerSecond: UInt256,
|
||||
collateralPerByte: UInt256,
|
||||
expiry: UInt256,
|
||||
expiry: uint64,
|
||||
): Future[?!PurchaseId] {.async.} =
|
||||
## Initiate a request for storage sequence, this might
|
||||
## be a multistep procedure.
|
||||
@ -531,7 +531,7 @@ proc requestStorage*(
|
||||
pricePerBytePerSecond = pricePerBytePerSecond
|
||||
proofProbability = proofProbability
|
||||
collateralPerByte = collateralPerByte
|
||||
expiry = expiry.truncate(int64)
|
||||
expiry = expiry
|
||||
now = self.clock.now
|
||||
|
||||
trace "Received a request for storage!"
|
||||
@ -553,7 +553,7 @@ proc requestStorage*(
|
||||
success purchase.id
|
||||
|
||||
proc onStore(
|
||||
self: CodexNodeRef, request: StorageRequest, slotIdx: UInt256, blocksCb: BlocksCb
|
||||
self: CodexNodeRef, request: StorageRequest, slotIdx: uint64, blocksCb: BlocksCb
|
||||
): Future[?!void] {.async.} =
|
||||
## store data in local storage
|
||||
##
|
||||
@ -575,11 +575,9 @@ proc onStore(
|
||||
trace "Unable to create slots builder", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
let
|
||||
slotIdx = slotIdx.truncate(int)
|
||||
expiry = request.expiry.toSecondsSince1970
|
||||
let expiry = request.expiry
|
||||
|
||||
if slotIdx > manifest.slotRoots.high:
|
||||
if slotIdx > manifest.slotRoots.high.uint64:
|
||||
trace "Slot index not in manifest", slotIdx
|
||||
return failure(newException(CodexError, "Slot index not in manifest"))
|
||||
|
||||
@ -587,7 +585,7 @@ proc onStore(
|
||||
trace "Updating expiry for blocks", blocks = blocks.len
|
||||
|
||||
let ensureExpiryFutures =
|
||||
blocks.mapIt(self.networkStore.ensureExpiry(it.cid, expiry))
|
||||
blocks.mapIt(self.networkStore.ensureExpiry(it.cid, expiry.toSecondsSince1970))
|
||||
if updateExpiryErr =? (await allFutureResult(ensureExpiryFutures)).errorOption:
|
||||
return failure(updateExpiryErr)
|
||||
|
||||
@ -603,7 +601,11 @@ proc onStore(
|
||||
trace "Unable to create indexing strategy from protected manifest", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
without blksIter =? indexer.getIndicies(slotIdx).catch, err:
|
||||
if slotIdx > int.high.uint64:
|
||||
error "Cannot cast slot index to int", slotIndex = slotIdx
|
||||
return
|
||||
|
||||
without blksIter =? indexer.getIndicies(slotIdx.int).catch, err:
|
||||
trace "Unable to get indicies from strategy", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
@ -613,13 +615,13 @@ proc onStore(
|
||||
trace "Unable to fetch blocks", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
without slotRoot =? (await builder.buildSlot(slotIdx.Natural)), err:
|
||||
without slotRoot =? (await builder.buildSlot(slotIdx.int)), err:
|
||||
trace "Unable to build slot", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
trace "Slot successfully retrieved and reconstructed"
|
||||
|
||||
if cid =? slotRoot.toSlotCid() and cid != manifest.slotRoots[slotIdx.int]:
|
||||
if cid =? slotRoot.toSlotCid() and cid != manifest.slotRoots[slotIdx]:
|
||||
trace "Slot root mismatch",
|
||||
manifest = manifest.slotRoots[slotIdx.int], recovered = slotRoot.toSlotCid()
|
||||
return failure(newException(CodexError, "Slot root mismatch"))
|
||||
@ -636,7 +638,7 @@ proc onProve(
|
||||
|
||||
let
|
||||
cidStr = $slot.request.content.cid
|
||||
slotIdx = slot.slotIndex.truncate(Natural)
|
||||
slotIdx = slot.slotIndex
|
||||
|
||||
logScope:
|
||||
cid = cidStr
|
||||
@ -657,7 +659,8 @@ proc onProve(
|
||||
return failure(err)
|
||||
|
||||
when defined(verify_circuit):
|
||||
without (inputs, proof) =? await prover.prove(slotIdx, manifest, challenge), err:
|
||||
without (inputs, proof) =? await prover.prove(slotIdx.int, manifest, challenge),
|
||||
err:
|
||||
error "Unable to generate proof", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
@ -671,7 +674,7 @@ proc onProve(
|
||||
|
||||
trace "Proof verified successfully"
|
||||
else:
|
||||
without (_, proof) =? await prover.prove(slotIdx, manifest, challenge), err:
|
||||
without (_, proof) =? await prover.prove(slotIdx.int, manifest, challenge), err:
|
||||
error "Unable to generate proof", err = err.msg
|
||||
return failure(err)
|
||||
|
||||
@ -688,7 +691,7 @@ proc onExpiryUpdate(
|
||||
): Future[?!void] {.async.} =
|
||||
return await self.updateExpiry(rootCid, expiry)
|
||||
|
||||
proc onClear(self: CodexNodeRef, request: StorageRequest, slotIndex: UInt256) =
|
||||
proc onClear(self: CodexNodeRef, request: StorageRequest, slotIndex: uint64) =
|
||||
# TODO: remove data from local storage
|
||||
discard
|
||||
|
||||
@ -704,7 +707,7 @@ proc start*(self: CodexNodeRef) {.async.} =
|
||||
|
||||
if hostContracts =? self.contracts.host:
|
||||
hostContracts.sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] =
|
||||
self.onStore(request, slot, onBatch)
|
||||
|
||||
@ -713,7 +716,7 @@ proc start*(self: CodexNodeRef) {.async.} =
|
||||
): Future[?!void] =
|
||||
self.onExpiryUpdate(rootCid, expiry)
|
||||
|
||||
hostContracts.sales.onClear = proc(request: StorageRequest, slotIndex: UInt256) =
|
||||
hostContracts.sales.onClear = proc(request: StorageRequest, slotIndex: uint64) =
|
||||
# TODO: remove data from local storage
|
||||
self.onClear(request, slotIndex)
|
||||
|
||||
|
||||
@ -2,10 +2,10 @@ import pkg/stint
|
||||
|
||||
type
|
||||
Periodicity* = object
|
||||
seconds*: UInt256
|
||||
seconds*: uint64
|
||||
|
||||
Period* = UInt256
|
||||
Timestamp* = UInt256
|
||||
Period* = uint64
|
||||
Timestamp* = uint64
|
||||
|
||||
func periodOf*(periodicity: Periodicity, timestamp: Timestamp): Period =
|
||||
timestamp div periodicity.seconds
|
||||
|
||||
@ -463,7 +463,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
|
||||
Http400, "Total size must be larger then zero", headers = headers
|
||||
)
|
||||
|
||||
if not reservations.hasAvailable(restAv.totalSize.truncate(uint)):
|
||||
if not reservations.hasAvailable(restAv.totalSize):
|
||||
return
|
||||
RestApiResponse.error(Http422, "Not enough storage quota", headers = headers)
|
||||
|
||||
|
||||
@ -13,11 +13,11 @@ export json
|
||||
|
||||
type
|
||||
StorageRequestParams* = object
|
||||
duration* {.serialize.}: UInt256
|
||||
duration* {.serialize.}: uint64
|
||||
proofProbability* {.serialize.}: UInt256
|
||||
pricePerBytePerSecond* {.serialize.}: UInt256
|
||||
collateralPerByte* {.serialize.}: UInt256
|
||||
expiry* {.serialize.}: ?UInt256
|
||||
expiry* {.serialize.}: ?uint64
|
||||
nodes* {.serialize.}: ?uint
|
||||
tolerance* {.serialize.}: ?uint
|
||||
|
||||
@ -28,16 +28,16 @@ type
|
||||
error* {.serialize.}: ?string
|
||||
|
||||
RestAvailability* = object
|
||||
totalSize* {.serialize.}: UInt256
|
||||
duration* {.serialize.}: UInt256
|
||||
totalSize* {.serialize.}: uint64
|
||||
duration* {.serialize.}: uint64
|
||||
minPricePerBytePerSecond* {.serialize.}: UInt256
|
||||
totalCollateral* {.serialize.}: UInt256
|
||||
freeSize* {.serialize.}: ?UInt256
|
||||
freeSize* {.serialize.}: ?uint64
|
||||
|
||||
RestSalesAgent* = object
|
||||
state* {.serialize.}: string
|
||||
requestId* {.serialize.}: RequestId
|
||||
slotIndex* {.serialize.}: UInt256
|
||||
slotIndex* {.serialize.}: uint64
|
||||
request* {.serialize.}: ?StorageRequest
|
||||
reservation* {.serialize.}: ?Reservation
|
||||
|
||||
|
||||
@ -150,16 +150,16 @@ proc cleanUp(
|
||||
).errorOption:
|
||||
error "failure deleting reservation", error = deleteErr.msg
|
||||
|
||||
if data.slotIndex > uint16.high.uint64:
|
||||
error "Cannot cast slot index to uint16", slotIndex = data.slotIndex
|
||||
return
|
||||
|
||||
# Re-add items back into the queue to prevent small availabilities from
|
||||
# draining the queue. Seen items will be ordered last.
|
||||
if reprocessSlot and request =? data.request:
|
||||
let queue = sales.context.slotQueue
|
||||
var seenItem = SlotQueueItem.init(
|
||||
data.requestId,
|
||||
data.slotIndex.truncate(uint16),
|
||||
data.ask,
|
||||
request.expiry,
|
||||
seen = true,
|
||||
data.requestId, data.slotIndex.uint16, data.ask, request.expiry, seen = true
|
||||
)
|
||||
trace "pushing ignored item to queue, marked as seen"
|
||||
if err =? queue.push(seenItem).errorOption:
|
||||
@ -172,7 +172,7 @@ proc cleanUp(
|
||||
processing.complete()
|
||||
|
||||
proc filled(
|
||||
sales: Sales, request: StorageRequest, slotIndex: UInt256, processing: Future[void]
|
||||
sales: Sales, request: StorageRequest, slotIndex: uint64, processing: Future[void]
|
||||
) =
|
||||
if onSale =? sales.context.onSale:
|
||||
onSale(request, slotIndex)
|
||||
@ -184,16 +184,15 @@ proc filled(
|
||||
proc processSlot(sales: Sales, item: SlotQueueItem, done: Future[void]) =
|
||||
debug "Processing slot from queue", requestId = item.requestId, slot = item.slotIndex
|
||||
|
||||
let agent = newSalesAgent(
|
||||
sales.context, item.requestId, item.slotIndex.u256, none StorageRequest
|
||||
)
|
||||
let agent =
|
||||
newSalesAgent(sales.context, item.requestId, item.slotIndex, none StorageRequest)
|
||||
|
||||
agent.onCleanUp = proc(
|
||||
returnBytes = false, reprocessSlot = false, returnedCollateral = UInt256.none
|
||||
) {.async.} =
|
||||
await sales.cleanUp(agent, returnBytes, reprocessSlot, returnedCollateral, done)
|
||||
|
||||
agent.onFilled = some proc(request: StorageRequest, slotIndex: UInt256) =
|
||||
agent.onFilled = some proc(request: StorageRequest, slotIndex: uint64) =
|
||||
sales.filled(request, slotIndex, done)
|
||||
|
||||
agent.start(SalePreparing())
|
||||
@ -283,7 +282,7 @@ proc onAvailabilityAdded(sales: Sales, availability: Availability) {.async.} =
|
||||
queue.unpause()
|
||||
|
||||
proc onStorageRequested(
|
||||
sales: Sales, requestId: RequestId, ask: StorageAsk, expiry: UInt256
|
||||
sales: Sales, requestId: RequestId, ask: StorageAsk, expiry: uint64
|
||||
) =
|
||||
logScope:
|
||||
topics = "marketplace sales onStorageRequested"
|
||||
@ -312,7 +311,7 @@ proc onStorageRequested(
|
||||
else:
|
||||
warn "Error adding request to SlotQueue", error = err.msg
|
||||
|
||||
proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: UInt256) =
|
||||
proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: uint64) =
|
||||
logScope:
|
||||
topics = "marketplace sales onSlotFreed"
|
||||
requestId
|
||||
@ -325,8 +324,12 @@ proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: UInt256) =
|
||||
let market = context.market
|
||||
let queue = context.slotQueue
|
||||
|
||||
# first attempt to populate request using existing slot metadata in queue
|
||||
without var found =? queue.populateItem(requestId, slotIndex.truncate(uint16)):
|
||||
if slotIndex > uint16.high.uint64:
|
||||
error "Cannot cast slot index to uint16, value = ", slotIndex
|
||||
return
|
||||
|
||||
# first attempt to populate request using existing metadata in queue
|
||||
without var found =? queue.populateItem(requestId, slotIndex.uint16):
|
||||
trace "no existing request metadata, getting request info from contract"
|
||||
# if there's no existing slot for that request, retrieve the request
|
||||
# from the contract.
|
||||
@ -335,7 +338,7 @@ proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: UInt256) =
|
||||
error "unknown request in contract"
|
||||
return
|
||||
|
||||
found = SlotQueueItem.init(request, slotIndex.truncate(uint16))
|
||||
found = SlotQueueItem.init(request, slotIndex.uint16)
|
||||
except CancelledError:
|
||||
discard # do not propagate as addSlotToQueue was asyncSpawned
|
||||
except CatchableError as e:
|
||||
@ -353,7 +356,7 @@ proc subscribeRequested(sales: Sales) {.async.} =
|
||||
let context = sales.context
|
||||
let market = context.market
|
||||
|
||||
proc onStorageRequested(requestId: RequestId, ask: StorageAsk, expiry: UInt256) =
|
||||
proc onStorageRequested(requestId: RequestId, ask: StorageAsk, expiry: uint64) =
|
||||
sales.onStorageRequested(requestId, ask, expiry)
|
||||
|
||||
try:
|
||||
@ -426,9 +429,13 @@ proc subscribeSlotFilled(sales: Sales) {.async.} =
|
||||
let market = context.market
|
||||
let queue = context.slotQueue
|
||||
|
||||
proc onSlotFilled(requestId: RequestId, slotIndex: UInt256) =
|
||||
proc onSlotFilled(requestId: RequestId, slotIndex: uint64) =
|
||||
if slotIndex > uint16.high.uint64:
|
||||
error "Cannot cast slot index to uint16, value = ", slotIndex
|
||||
return
|
||||
|
||||
trace "slot filled, removing from slot queue", requestId, slotIndex
|
||||
queue.delete(requestId, slotIndex.truncate(uint16))
|
||||
queue.delete(requestId, slotIndex.uint16)
|
||||
|
||||
for agent in sales.agents:
|
||||
agent.onSlotFilled(requestId, slotIndex)
|
||||
@ -445,7 +452,7 @@ proc subscribeSlotFreed(sales: Sales) {.async.} =
|
||||
let context = sales.context
|
||||
let market = context.market
|
||||
|
||||
proc onSlotFreed(requestId: RequestId, slotIndex: UInt256) =
|
||||
proc onSlotFreed(requestId: RequestId, slotIndex: uint64) =
|
||||
sales.onSlotFreed(requestId, slotIndex)
|
||||
|
||||
try:
|
||||
@ -461,9 +468,13 @@ proc subscribeSlotReservationsFull(sales: Sales) {.async.} =
|
||||
let market = context.market
|
||||
let queue = context.slotQueue
|
||||
|
||||
proc onSlotReservationsFull(requestId: RequestId, slotIndex: UInt256) =
|
||||
proc onSlotReservationsFull(requestId: RequestId, slotIndex: uint64) =
|
||||
if slotIndex > uint16.high.uint64:
|
||||
error "Cannot cast slot index to uint16, value = ", slotIndex
|
||||
return
|
||||
|
||||
trace "reservations for slot full, removing from slot queue", requestId, slotIndex
|
||||
queue.delete(requestId, slotIndex.truncate(uint16))
|
||||
queue.delete(requestId, slotIndex.uint16)
|
||||
|
||||
try:
|
||||
let sub = await market.subscribeSlotReservationsFull(onSlotReservationsFull)
|
||||
|
||||
@ -64,9 +64,9 @@ type
|
||||
SomeStorableId = AvailabilityId | ReservationId
|
||||
Availability* = ref object
|
||||
id* {.serialize.}: AvailabilityId
|
||||
totalSize* {.serialize.}: UInt256
|
||||
freeSize* {.serialize.}: UInt256
|
||||
duration* {.serialize.}: UInt256
|
||||
totalSize* {.serialize.}: uint64
|
||||
freeSize* {.serialize.}: uint64
|
||||
duration* {.serialize.}: uint64
|
||||
minPricePerBytePerSecond* {.serialize.}: UInt256
|
||||
totalCollateral {.serialize.}: UInt256
|
||||
totalRemainingCollateral* {.serialize.}: UInt256
|
||||
@ -74,9 +74,9 @@ type
|
||||
Reservation* = ref object
|
||||
id* {.serialize.}: ReservationId
|
||||
availabilityId* {.serialize.}: AvailabilityId
|
||||
size* {.serialize.}: UInt256
|
||||
size* {.serialize.}: uint64
|
||||
requestId* {.serialize.}: RequestId
|
||||
slotIndex* {.serialize.}: UInt256
|
||||
slotIndex* {.serialize.}: uint64
|
||||
|
||||
Reservations* = ref object of RootObj
|
||||
availabilityLock: AsyncLock
|
||||
@ -123,9 +123,9 @@ proc new*(T: type Reservations, repo: RepoStore): Reservations =
|
||||
|
||||
proc init*(
|
||||
_: type Availability,
|
||||
totalSize: UInt256,
|
||||
freeSize: UInt256,
|
||||
duration: UInt256,
|
||||
totalSize: uint64,
|
||||
freeSize: uint64,
|
||||
duration: uint64,
|
||||
minPricePerBytePerSecond: UInt256,
|
||||
totalCollateral: UInt256,
|
||||
): Availability =
|
||||
@ -151,9 +151,9 @@ proc `totalCollateral=`*(self: Availability, value: UInt256) {.inline.} =
|
||||
proc init*(
|
||||
_: type Reservation,
|
||||
availabilityId: AvailabilityId,
|
||||
size: UInt256,
|
||||
size: uint64,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
): Reservation =
|
||||
var id: array[32, byte]
|
||||
doAssert randomBytes(id) == 32
|
||||
@ -206,7 +206,7 @@ func key*(availability: Availability): ?!Key =
|
||||
return availability.id.key
|
||||
|
||||
func maxCollateralPerByte*(availability: Availability): UInt256 =
|
||||
return availability.totalRemainingCollateral div availability.freeSize
|
||||
return availability.totalRemainingCollateral div availability.freeSize.stuint(256)
|
||||
|
||||
func key*(reservation: Reservation): ?!Key =
|
||||
return key(reservation.id, reservation.availabilityId)
|
||||
@ -289,16 +289,12 @@ proc updateAvailability(
|
||||
trace "totalSize changed, updating repo reservation"
|
||||
if oldAvailability.totalSize < obj.totalSize: # storage added
|
||||
if reserveErr =? (
|
||||
await self.repo.reserve(
|
||||
(obj.totalSize - oldAvailability.totalSize).truncate(uint).NBytes
|
||||
)
|
||||
await self.repo.reserve((obj.totalSize - oldAvailability.totalSize).NBytes)
|
||||
).errorOption:
|
||||
return failure(reserveErr.toErr(ReserveFailedError))
|
||||
elif oldAvailability.totalSize > obj.totalSize: # storage removed
|
||||
if reserveErr =? (
|
||||
await self.repo.release(
|
||||
(oldAvailability.totalSize - obj.totalSize).truncate(uint).NBytes
|
||||
)
|
||||
await self.repo.release((oldAvailability.totalSize - obj.totalSize).NBytes)
|
||||
).errorOption:
|
||||
return failure(reserveErr.toErr(ReleaseFailedError))
|
||||
|
||||
@ -361,7 +357,7 @@ proc deleteReservation*(
|
||||
else:
|
||||
return failure(error)
|
||||
|
||||
if reservation.size > 0.u256:
|
||||
if reservation.size > 0.uint64:
|
||||
trace "returning remaining reservation bytes to availability",
|
||||
size = reservation.size
|
||||
|
||||
@ -389,8 +385,8 @@ proc deleteReservation*(
|
||||
|
||||
proc createAvailability*(
|
||||
self: Reservations,
|
||||
size: UInt256,
|
||||
duration: UInt256,
|
||||
size: uint64,
|
||||
duration: uint64,
|
||||
minPricePerBytePerSecond: UInt256,
|
||||
totalCollateral: UInt256,
|
||||
): Future[?!Availability] {.async.} =
|
||||
@ -399,7 +395,7 @@ proc createAvailability*(
|
||||
|
||||
let availability =
|
||||
Availability.init(size, size, duration, minPricePerBytePerSecond, totalCollateral)
|
||||
let bytes = availability.freeSize.truncate(uint)
|
||||
let bytes = availability.freeSize
|
||||
|
||||
if reserveErr =? (await self.repo.reserve(bytes.NBytes)).errorOption:
|
||||
return failure(reserveErr.toErr(ReserveFailedError))
|
||||
@ -418,9 +414,9 @@ proc createAvailability*(
|
||||
method createReservation*(
|
||||
self: Reservations,
|
||||
availabilityId: AvailabilityId,
|
||||
slotSize: UInt256,
|
||||
slotSize: uint64,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
collateralPerByte: UInt256,
|
||||
): Future[?!Reservation] {.async, base.} =
|
||||
withLock(self.availabilityLock):
|
||||
@ -450,7 +446,7 @@ method createReservation*(
|
||||
availability.freeSize -= slotSize
|
||||
|
||||
# adjust the remaining totalRemainingCollateral
|
||||
availability.totalRemainingCollateral -= slotSize * collateralPerByte
|
||||
availability.totalRemainingCollateral -= slotSize.stuint(256) * collateralPerByte
|
||||
|
||||
# update availability with reduced size
|
||||
trace "Updating availability with reduced size"
|
||||
@ -475,7 +471,7 @@ proc returnBytesToAvailability*(
|
||||
self: Reservations,
|
||||
availabilityId: AvailabilityId,
|
||||
reservationId: ReservationId,
|
||||
bytes: UInt256,
|
||||
bytes: uint64,
|
||||
): Future[?!void] {.async.} =
|
||||
logScope:
|
||||
reservationId
|
||||
@ -502,8 +498,7 @@ proc returnBytesToAvailability*(
|
||||
|
||||
# First lets see if we can re-reserve the bytes, if the Repo's quota
|
||||
# is depleted then we will fail-fast as there is nothing to be done atm.
|
||||
if reserveErr =?
|
||||
(await self.repo.reserve(bytesToBeReturned.truncate(uint).NBytes)).errorOption:
|
||||
if reserveErr =? (await self.repo.reserve(bytesToBeReturned.NBytes)).errorOption:
|
||||
return failure(reserveErr.toErr(ReserveFailedError))
|
||||
|
||||
without availabilityKey =? availabilityId.key, error:
|
||||
@ -517,8 +512,7 @@ proc returnBytesToAvailability*(
|
||||
# Update availability with returned size
|
||||
if updateErr =? (await self.updateAvailability(availability)).errorOption:
|
||||
trace "Rolling back returning bytes"
|
||||
if rollbackErr =?
|
||||
(await self.repo.release(bytesToBeReturned.truncate(uint).NBytes)).errorOption:
|
||||
if rollbackErr =? (await self.repo.release(bytesToBeReturned.NBytes)).errorOption:
|
||||
rollbackErr.parent = updateErr
|
||||
return failure(rollbackErr)
|
||||
|
||||
@ -546,7 +540,7 @@ proc release*(
|
||||
without var reservation =? (await self.get(key, Reservation)), error:
|
||||
return failure(error)
|
||||
|
||||
if reservation.size < bytes.u256:
|
||||
if reservation.size < bytes:
|
||||
let error = newException(
|
||||
BytesOutOfBoundsError,
|
||||
"trying to release an amount of bytes that is greater than the total size of the Reservation",
|
||||
@ -556,7 +550,7 @@ proc release*(
|
||||
if releaseErr =? (await self.repo.release(bytes.NBytes)).errorOption:
|
||||
return failure(releaseErr.toErr(ReleaseFailedError))
|
||||
|
||||
reservation.size -= bytes.u256
|
||||
reservation.size -= bytes
|
||||
|
||||
# persist partially used Reservation with updated size
|
||||
if err =? (await self.update(reservation)).errorOption:
|
||||
@ -643,7 +637,8 @@ proc all*(
|
||||
|
||||
proc findAvailability*(
|
||||
self: Reservations,
|
||||
size, duration, pricePerBytePerSecond, collateralPerByte: UInt256,
|
||||
size, duration: uint64,
|
||||
pricePerBytePerSecond, collateralPerByte: UInt256,
|
||||
): Future[?Availability] {.async.} =
|
||||
without storables =? (await self.storables(Availability)), e:
|
||||
error "failed to get all storables", error = e.msg
|
||||
|
||||
@ -29,7 +29,7 @@ type
|
||||
OnCleanUp* = proc(
|
||||
returnBytes = false, reprocessSlot = false, returnedCollateral = UInt256.none
|
||||
): Future[void] {.gcsafe, upraises: [].}
|
||||
OnFilled* = proc(request: StorageRequest, slotIndex: UInt256) {.gcsafe, upraises: [].}
|
||||
OnFilled* = proc(request: StorageRequest, slotIndex: uint64) {.gcsafe, upraises: [].}
|
||||
|
||||
SalesAgentError = object of CodexError
|
||||
AllSlotsFilledError* = object of SalesAgentError
|
||||
@ -40,7 +40,7 @@ func `==`*(a, b: SalesAgent): bool =
|
||||
proc newSalesAgent*(
|
||||
context: SalesContext,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
request: ?StorageRequest,
|
||||
): SalesAgent =
|
||||
var agent = SalesAgent.new()
|
||||
@ -121,7 +121,7 @@ method onFailed*(
|
||||
agent.schedule(failedEvent(request))
|
||||
|
||||
method onSlotFilled*(
|
||||
agent: SalesAgent, requestId: RequestId, slotIndex: UInt256
|
||||
agent: SalesAgent, requestId: RequestId, slotIndex: uint64
|
||||
) {.base, gcsafe, upraises: [].} =
|
||||
if agent.data.requestId == requestId and agent.data.slotIndex == slotIndex:
|
||||
agent.schedule(slotFilledEvent(requestId, slotIndex))
|
||||
|
||||
@ -26,7 +26,7 @@ type
|
||||
|
||||
BlocksCb* = proc(blocks: seq[bt.Block]): Future[?!void] {.gcsafe, raises: [].}
|
||||
OnStore* = proc(
|
||||
request: StorageRequest, slot: UInt256, blocksCb: BlocksCb
|
||||
request: StorageRequest, slot: uint64, blocksCb: BlocksCb
|
||||
): Future[?!void] {.gcsafe, upraises: [].}
|
||||
OnProve* = proc(slot: Slot, challenge: ProofChallenge): Future[?!Groth16Proof] {.
|
||||
gcsafe, upraises: []
|
||||
@ -34,5 +34,5 @@ type
|
||||
OnExpiryUpdate* = proc(rootCid: Cid, expiry: SecondsSince1970): Future[?!void] {.
|
||||
gcsafe, upraises: []
|
||||
.}
|
||||
OnClear* = proc(request: StorageRequest, slotIndex: UInt256) {.gcsafe, upraises: [].}
|
||||
OnSale* = proc(request: StorageRequest, slotIndex: UInt256) {.gcsafe, upraises: [].}
|
||||
OnClear* = proc(request: StorageRequest, slotIndex: uint64) {.gcsafe, upraises: [].}
|
||||
OnSale* = proc(request: StorageRequest, slotIndex: uint64) {.gcsafe, upraises: [].}
|
||||
|
||||
@ -7,6 +7,6 @@ type SalesData* = ref object
|
||||
requestId*: RequestId
|
||||
ask*: StorageAsk
|
||||
request*: ?StorageRequest
|
||||
slotIndex*: UInt256
|
||||
slotIndex*: uint64
|
||||
cancelled*: Future[void]
|
||||
reservation*: ?Reservation
|
||||
|
||||
@ -5,6 +5,7 @@ import pkg/questionable
|
||||
import pkg/questionable/results
|
||||
import pkg/upraises
|
||||
import ../errors
|
||||
import ../clock
|
||||
import ../logutils
|
||||
import ../rng
|
||||
import ../utils
|
||||
@ -30,11 +31,11 @@ type
|
||||
SlotQueueItem* = object
|
||||
requestId: RequestId
|
||||
slotIndex: uint16
|
||||
slotSize: UInt256
|
||||
duration: UInt256
|
||||
slotSize: uint64
|
||||
duration: uint64
|
||||
pricePerBytePerSecond: UInt256
|
||||
collateralPerByte: UInt256
|
||||
expiry: UInt256
|
||||
expiry: uint64
|
||||
seen: bool
|
||||
|
||||
# don't need to -1 to prevent overflow when adding 1 (to always allow push)
|
||||
@ -135,7 +136,7 @@ proc init*(
|
||||
requestId: RequestId,
|
||||
slotIndex: uint16,
|
||||
ask: StorageAsk,
|
||||
expiry: UInt256,
|
||||
expiry: uint64,
|
||||
seen = false,
|
||||
): SlotQueueItem =
|
||||
SlotQueueItem(
|
||||
@ -155,7 +156,7 @@ proc init*(
|
||||
SlotQueueItem.init(request.id, slotIndex, request.ask, request.expiry)
|
||||
|
||||
proc init*(
|
||||
_: type SlotQueueItem, requestId: RequestId, ask: StorageAsk, expiry: UInt256
|
||||
_: type SlotQueueItem, requestId: RequestId, ask: StorageAsk, expiry: uint64
|
||||
): seq[SlotQueueItem] =
|
||||
if not ask.slots.inRange:
|
||||
raise newException(SlotsOutOfRangeError, "Too many slots")
|
||||
@ -182,10 +183,10 @@ proc requestId*(self: SlotQueueItem): RequestId =
|
||||
proc slotIndex*(self: SlotQueueItem): uint16 =
|
||||
self.slotIndex
|
||||
|
||||
proc slotSize*(self: SlotQueueItem): UInt256 =
|
||||
proc slotSize*(self: SlotQueueItem): uint64 =
|
||||
self.slotSize
|
||||
|
||||
proc duration*(self: SlotQueueItem): UInt256 =
|
||||
proc duration*(self: SlotQueueItem): uint64 =
|
||||
self.duration
|
||||
|
||||
proc pricePerBytePerSecond*(self: SlotQueueItem): UInt256 =
|
||||
|
||||
@ -25,7 +25,7 @@ method onFailed*(
|
||||
discard
|
||||
|
||||
method onSlotFilled*(
|
||||
state: SaleState, requestId: RequestId, slotIndex: UInt256
|
||||
state: SaleState, requestId: RequestId, slotIndex: uint64
|
||||
): ?State {.base, upraises: [].} =
|
||||
discard
|
||||
|
||||
@ -37,6 +37,6 @@ proc failedEvent*(request: StorageRequest): Event =
|
||||
return proc(state: State): ?State =
|
||||
SaleState(state).onFailed(request)
|
||||
|
||||
proc slotFilledEvent*(requestId: RequestId, slotIndex: UInt256): Event =
|
||||
proc slotFilledEvent*(requestId: RequestId, slotIndex: uint64): Event =
|
||||
return proc(state: State): ?State =
|
||||
SaleState(state).onSlotFilled(requestId, slotIndex)
|
||||
|
||||
@ -28,7 +28,7 @@ method onFailed*(state: SaleDownloading, request: StorageRequest): ?State =
|
||||
return some State(SaleFailed())
|
||||
|
||||
method onSlotFilled*(
|
||||
state: SaleDownloading, requestId: RequestId, slotIndex: UInt256
|
||||
state: SaleDownloading, requestId: RequestId, slotIndex: uint64
|
||||
): ?State =
|
||||
return some State(SaleFilled())
|
||||
|
||||
|
||||
@ -25,9 +25,9 @@ method onFailed*(state: SaleInitialProving, request: StorageRequest): ?State =
|
||||
|
||||
proc waitUntilNextPeriod(clock: Clock, periodicity: Periodicity) {.async.} =
|
||||
trace "Waiting until next period"
|
||||
let period = periodicity.periodOf(clock.now().u256)
|
||||
let periodEnd = periodicity.periodEnd(period).truncate(int64)
|
||||
await clock.waitUntil(periodEnd + 1)
|
||||
let period = periodicity.periodOf(clock.now().Timestamp)
|
||||
let periodEnd = periodicity.periodEnd(period)
|
||||
await clock.waitUntil((periodEnd + 1).toSecondsSince1970)
|
||||
|
||||
proc waitForStableChallenge(market: Market, clock: Clock, slotId: SlotId) {.async.} =
|
||||
let periodicity = await market.periodicity()
|
||||
|
||||
@ -33,7 +33,7 @@ method onFailed*(state: SalePreparing, request: StorageRequest): ?State =
|
||||
return some State(SaleFailed())
|
||||
|
||||
method onSlotFilled*(
|
||||
state: SalePreparing, requestId: RequestId, slotIndex: UInt256
|
||||
state: SalePreparing, requestId: RequestId, slotIndex: uint64
|
||||
): ?State =
|
||||
return some State(SaleFilled())
|
||||
|
||||
|
||||
@ -46,7 +46,7 @@ proc proveLoop(
|
||||
market: Market,
|
||||
clock: Clock,
|
||||
request: StorageRequest,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
onProve: OnProve,
|
||||
) {.async.} =
|
||||
let slot = Slot(request: request, slotIndex: slotIndex)
|
||||
@ -60,12 +60,12 @@ proc proveLoop(
|
||||
|
||||
proc getCurrentPeriod(): Future[Period] {.async.} =
|
||||
let periodicity = await market.periodicity()
|
||||
return periodicity.periodOf(clock.now().u256)
|
||||
return periodicity.periodOf(clock.now().Timestamp)
|
||||
|
||||
proc waitUntilPeriod(period: Period) {.async.} =
|
||||
let periodicity = await market.periodicity()
|
||||
# Ensure that we're past the period boundary by waiting an additional second
|
||||
await clock.waitUntil(periodicity.periodStart(period).truncate(int64) + 1)
|
||||
await clock.waitUntil((periodicity.periodStart(period) + 1).toSecondsSince1970)
|
||||
|
||||
while true:
|
||||
let currentPeriod = await getCurrentPeriod()
|
||||
|
||||
@ -20,7 +20,7 @@ when codex_enable_proof_failures:
|
||||
failEveryNProofs*: int
|
||||
proofCount: int
|
||||
|
||||
proc onSubmitProofError(error: ref CatchableError, period: UInt256, slotId: SlotId) =
|
||||
proc onSubmitProofError(error: ref CatchableError, period: Period, slotId: SlotId) =
|
||||
error "Submitting invalid proof failed", period, slotId, msg = error.msgDetail
|
||||
|
||||
method prove*(
|
||||
|
||||
@ -2,6 +2,7 @@ import std/sets
|
||||
import std/sequtils
|
||||
import pkg/chronos
|
||||
import pkg/questionable/results
|
||||
import pkg/stew/endians2
|
||||
|
||||
import ./validationconfig
|
||||
import ./market
|
||||
@ -19,7 +20,7 @@ type Validation* = ref object
|
||||
subscriptions: seq[Subscription]
|
||||
running: Future[void]
|
||||
periodicity: Periodicity
|
||||
proofTimeout: UInt256
|
||||
proofTimeout: uint64
|
||||
config: ValidationConfig
|
||||
|
||||
logScope:
|
||||
@ -33,18 +34,19 @@ proc new*(
|
||||
proc slots*(validation: Validation): seq[SlotId] =
|
||||
validation.slots.toSeq
|
||||
|
||||
proc getCurrentPeriod(validation: Validation): UInt256 =
|
||||
return validation.periodicity.periodOf(validation.clock.now().u256)
|
||||
proc getCurrentPeriod(validation: Validation): Period =
|
||||
return validation.periodicity.periodOf(validation.clock.now().Timestamp)
|
||||
|
||||
proc waitUntilNextPeriod(validation: Validation) {.async.} =
|
||||
let period = validation.getCurrentPeriod()
|
||||
let periodEnd = validation.periodicity.periodEnd(period)
|
||||
trace "Waiting until next period", currentPeriod = period
|
||||
await validation.clock.waitUntil(periodEnd.truncate(int64) + 1)
|
||||
await validation.clock.waitUntil((periodEnd + 1).toSecondsSince1970)
|
||||
|
||||
func groupIndexForSlotId*(slotId: SlotId, validationGroups: ValidationGroups): uint16 =
|
||||
let slotIdUInt256 = UInt256.fromBytesBE(slotId.toArray)
|
||||
(slotIdUInt256 mod validationGroups.u256).truncate(uint16)
|
||||
let a = slotId.toArray
|
||||
let slotIdInt64 = uint64.fromBytesBE(a)
|
||||
(slotIdInt64 mod uint64(validationGroups)).uint16
|
||||
|
||||
func maxSlotsConstraintRespected(validation: Validation): bool =
|
||||
validation.config.maxSlots == 0 or validation.slots.len < validation.config.maxSlots
|
||||
@ -55,7 +57,7 @@ func shouldValidateSlot(validation: Validation, slotId: SlotId): bool =
|
||||
groupIndexForSlotId(slotId, validationGroups) == validation.config.groupIndex
|
||||
|
||||
proc subscribeSlotFilled(validation: Validation) {.async.} =
|
||||
proc onSlotFilled(requestId: RequestId, slotIndex: UInt256) =
|
||||
proc onSlotFilled(requestId: RequestId, slotIndex: uint64) =
|
||||
if not validation.maxSlotsConstraintRespected:
|
||||
return
|
||||
let slotId = slotId(requestId, slotIndex)
|
||||
@ -113,17 +115,13 @@ proc run(validation: Validation) {.async: (raises: []).} =
|
||||
except CatchableError as e:
|
||||
error "Validation failed", msg = e.msg
|
||||
|
||||
proc epochForDurationBackFromNow(
|
||||
validation: Validation, duration: Duration
|
||||
): SecondsSince1970 =
|
||||
return validation.clock.now - duration.secs
|
||||
proc findEpoch(validation: Validation, secondsAgo: uint64): SecondsSince1970 =
|
||||
return validation.clock.now - secondsAgo.int64
|
||||
|
||||
proc restoreHistoricalState(validation: Validation) {.async.} =
|
||||
trace "Restoring historical state..."
|
||||
let requestDurationLimit = await validation.market.requestDurationLimit
|
||||
let startTimeEpoch = validation.epochForDurationBackFromNow(
|
||||
seconds(requestDurationLimit.truncate(int64))
|
||||
)
|
||||
let startTimeEpoch = validation.findEpoch(secondsAgo = requestDurationLimit)
|
||||
let slotFilledEvents =
|
||||
await validation.market.queryPastSlotFilledEvents(fromTime = startTimeEpoch)
|
||||
for event in slotFilledEvents:
|
||||
|
||||
@ -68,19 +68,19 @@ proc example*(_: type MultiHash, mcodec = Sha256HashCodec): MultiHash =
|
||||
proc example*(
|
||||
_: type Availability, collateralPerByte = uint8.example.u256
|
||||
): Availability =
|
||||
let totalSize = uint16.example.u256
|
||||
let totalSize = uint16.example.uint64
|
||||
Availability.init(
|
||||
totalSize = totalSize,
|
||||
freeSize = uint16.example.u256,
|
||||
duration = uint16.example.u256,
|
||||
freeSize = uint16.example.uint64,
|
||||
duration = uint16.example.uint64,
|
||||
minPricePerBytePerSecond = uint8.example.u256,
|
||||
totalCollateral = totalSize * collateralPerByte,
|
||||
totalCollateral = totalSize.u256 * collateralPerByte,
|
||||
)
|
||||
|
||||
proc example*(_: type Reservation): Reservation =
|
||||
Reservation.init(
|
||||
availabilityId = AvailabilityId(array[32, byte].example),
|
||||
size = uint16.example.u256,
|
||||
size = uint16.example.uint64,
|
||||
slotId = SlotId.example,
|
||||
)
|
||||
|
||||
|
||||
@ -57,7 +57,7 @@ type
|
||||
MockSlot* = object
|
||||
requestId*: RequestId
|
||||
host*: Address
|
||||
slotIndex*: UInt256
|
||||
slotIndex*: uint64
|
||||
proof*: Groth16Proof
|
||||
timestamp: ?SecondsSince1970
|
||||
collateral*: UInt256
|
||||
@ -84,7 +84,7 @@ type
|
||||
SlotFilledSubscription* = ref object of Subscription
|
||||
market: MockMarket
|
||||
requestId: ?RequestId
|
||||
slotIndex: ?UInt256
|
||||
slotIndex: ?uint64
|
||||
callback: OnSlotFilled
|
||||
|
||||
SlotFreedSubscription* = ref object of Subscription
|
||||
@ -126,10 +126,13 @@ proc new*(_: type MockMarket, clock: ?Clock = Clock.none): MockMarket =
|
||||
validatorRewardPercentage: 20,
|
||||
),
|
||||
proofs: ProofConfig(
|
||||
period: 10.u256, timeout: 5.u256, downtime: 64.uint8, downtimeProduct: 67.uint8
|
||||
period: 10.Period,
|
||||
timeout: 5.uint64,
|
||||
downtime: 64.uint8,
|
||||
downtimeProduct: 67.uint8,
|
||||
),
|
||||
reservations: SlotReservationsConfig(maxReservations: 3),
|
||||
requestDurationLimit: (60 * 60 * 24 * 30).u256,
|
||||
requestDurationLimit: (60 * 60 * 24 * 30).uint64,
|
||||
)
|
||||
MockMarket(
|
||||
signer: Address.example, config: config, canReserveSlot: true, clock: clock
|
||||
@ -141,10 +144,10 @@ method getSigner*(market: MockMarket): Future[Address] {.async.} =
|
||||
method periodicity*(mock: MockMarket): Future[Periodicity] {.async.} =
|
||||
return Periodicity(seconds: mock.config.proofs.period)
|
||||
|
||||
method proofTimeout*(market: MockMarket): Future[UInt256] {.async.} =
|
||||
method proofTimeout*(market: MockMarket): Future[uint64] {.async.} =
|
||||
return market.config.proofs.timeout
|
||||
|
||||
method requestDurationLimit*(market: MockMarket): Future[UInt256] {.async.} =
|
||||
method requestDurationLimit*(market: MockMarket): Future[uint64] {.async.} =
|
||||
return market.config.requestDurationLimit
|
||||
|
||||
method proofDowntime*(market: MockMarket): Future[uint8] {.async.} =
|
||||
@ -176,9 +179,9 @@ method getRequest*(
|
||||
return some request
|
||||
return none StorageRequest
|
||||
|
||||
method getActiveSlot*(market: MockMarket, slotId: SlotId): Future[?Slot] {.async.} =
|
||||
method getActiveSlot*(market: MockMarket, id: SlotId): Future[?Slot] {.async.} =
|
||||
for slot in market.filled:
|
||||
if slotId(slot.requestId, slot.slotIndex) == slotId and
|
||||
if slotId(slot.requestId, slot.slotIndex) == id and
|
||||
request =? await market.getRequest(slot.requestId):
|
||||
return some Slot(request: request, slotIndex: slot.slotIndex)
|
||||
return none Slot
|
||||
@ -204,7 +207,7 @@ method requestExpiresAt*(
|
||||
return market.requestExpiry[id]
|
||||
|
||||
method getHost*(
|
||||
market: MockMarket, requestId: RequestId, slotIndex: UInt256
|
||||
market: MockMarket, requestId: RequestId, slotIndex: uint64
|
||||
): Future[?Address] {.async.} =
|
||||
for slot in market.filled:
|
||||
if slot.requestId == requestId and slot.slotIndex == slotIndex:
|
||||
@ -219,7 +222,7 @@ method currentCollateral*(
|
||||
return slot.collateral
|
||||
return 0.u256
|
||||
|
||||
proc emitSlotFilled*(market: MockMarket, requestId: RequestId, slotIndex: UInt256) =
|
||||
proc emitSlotFilled*(market: MockMarket, requestId: RequestId, slotIndex: uint64) =
|
||||
var subscriptions = market.subscriptions.onSlotFilled
|
||||
for subscription in subscriptions:
|
||||
let requestMatches =
|
||||
@ -229,13 +232,13 @@ proc emitSlotFilled*(market: MockMarket, requestId: RequestId, slotIndex: UInt25
|
||||
if requestMatches and slotMatches:
|
||||
subscription.callback(requestId, slotIndex)
|
||||
|
||||
proc emitSlotFreed*(market: MockMarket, requestId: RequestId, slotIndex: UInt256) =
|
||||
proc emitSlotFreed*(market: MockMarket, requestId: RequestId, slotIndex: uint64) =
|
||||
var subscriptions = market.subscriptions.onSlotFreed
|
||||
for subscription in subscriptions:
|
||||
subscription.callback(requestId, slotIndex)
|
||||
|
||||
proc emitSlotReservationsFull*(
|
||||
market: MockMarket, requestId: RequestId, slotIndex: UInt256
|
||||
market: MockMarket, requestId: RequestId, slotIndex: uint64
|
||||
) =
|
||||
var subscriptions = market.subscriptions.onSlotReservationsFull
|
||||
for subscription in subscriptions:
|
||||
@ -262,7 +265,7 @@ proc emitRequestFailed*(market: MockMarket, requestId: RequestId) =
|
||||
proc fillSlot*(
|
||||
market: MockMarket,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
proof: Groth16Proof,
|
||||
host: Address,
|
||||
collateral = 0.u256,
|
||||
@ -282,7 +285,7 @@ proc fillSlot*(
|
||||
method fillSlot*(
|
||||
market: MockMarket,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
proof: Groth16Proof,
|
||||
collateral: UInt256,
|
||||
) {.async.} =
|
||||
@ -346,13 +349,13 @@ method canProofBeMarkedAsMissing*(
|
||||
return market.canBeMarkedAsMissing.contains(id)
|
||||
|
||||
method reserveSlot*(
|
||||
market: MockMarket, requestId: RequestId, slotIndex: UInt256
|
||||
market: MockMarket, requestId: RequestId, slotIndex: uint64
|
||||
) {.async.} =
|
||||
if error =? market.reserveSlotThrowError:
|
||||
raise error
|
||||
|
||||
method canReserveSlot*(
|
||||
market: MockMarket, requestId: RequestId, slotIndex: UInt256
|
||||
market: MockMarket, requestId: RequestId, slotIndex: uint64
|
||||
): Future[bool] {.async.} =
|
||||
return market.canReserveSlot
|
||||
|
||||
@ -395,7 +398,7 @@ method subscribeSlotFilled*(
|
||||
return subscription
|
||||
|
||||
method subscribeSlotFilled*(
|
||||
market: MockMarket, requestId: RequestId, slotIndex: UInt256, callback: OnSlotFilled
|
||||
market: MockMarket, requestId: RequestId, slotIndex: uint64, callback: OnSlotFilled
|
||||
): Future[Subscription] {.async.} =
|
||||
let subscription = SlotFilledSubscription(
|
||||
market: market,
|
||||
|
||||
@ -24,9 +24,9 @@ proc setCreateReservationThrowError*(
|
||||
method createReservation*(
|
||||
self: MockReservations,
|
||||
availabilityId: AvailabilityId,
|
||||
slotSize: UInt256,
|
||||
slotSize: uint64,
|
||||
requestId: RequestId,
|
||||
slotIndex: UInt256,
|
||||
slotIndex: uint64,
|
||||
collateralPerByte: UInt256,
|
||||
): Future[?!Reservation] {.async.} =
|
||||
if self.createReservationThrowBytesOutOfBoundsError:
|
||||
|
||||
@ -12,6 +12,6 @@ method onFailed*(agent: SalesAgent, requestId: RequestId) =
|
||||
failedCalled = true
|
||||
|
||||
method onSlotFilled*(
|
||||
agent: SalesAgent, requestId: RequestId, slotIndex: UInt256
|
||||
agent: SalesAgent, requestId: RequestId, slotIndex: uint64
|
||||
) {.base.} =
|
||||
slotFilledCalled = true
|
||||
|
||||
@ -4,11 +4,11 @@ import pkg/codex/sales/slotqueue
|
||||
type MockSlotQueueItem* = object
|
||||
requestId*: RequestId
|
||||
slotIndex*: uint16
|
||||
slotSize*: UInt256
|
||||
duration*: UInt256
|
||||
slotSize*: uint64
|
||||
duration*: uint64
|
||||
pricePerBytePerSecond*: UInt256
|
||||
collateralPerByte*: UInt256
|
||||
expiry*: UInt256
|
||||
expiry*: uint64
|
||||
seen*: bool
|
||||
|
||||
proc toSlotQueueItem*(item: MockSlotQueueItem): SlotQueueItem =
|
||||
|
||||
@ -116,7 +116,8 @@ asyncchecksuite "Test Node - Host contracts":
|
||||
let onStore = !sales.onStore
|
||||
var request = StorageRequest.example
|
||||
request.content.cid = verifiableBlock.cid
|
||||
request.expiry = (getTime() + DefaultBlockTtl.toTimesDuration + 1.hours).toUnix.u256
|
||||
request.expiry =
|
||||
(getTime() + DefaultBlockTtl.toTimesDuration + 1.hours).toUnix.uint64
|
||||
var fetchedBytes: uint = 0
|
||||
|
||||
let onBlocks = proc(blocks: seq[bt.Block]): Future[?!void] {.async.} =
|
||||
@ -124,7 +125,7 @@ asyncchecksuite "Test Node - Host contracts":
|
||||
fetchedBytes += blk.data.len.uint
|
||||
return success()
|
||||
|
||||
(await onStore(request, 1.u256, onBlocks)).tryGet()
|
||||
(await onStore(request, 1.uint64, onBlocks)).tryGet()
|
||||
check fetchedBytes == 12 * DefaultBlockSize.uint
|
||||
|
||||
let indexer = verifiable.protectedStrategy.init(
|
||||
|
||||
@ -157,10 +157,10 @@ asyncchecksuite "Test Node - Basic":
|
||||
cid = manifestBlock.cid,
|
||||
nodes = 5,
|
||||
tolerance = 2,
|
||||
duration = 100.u256,
|
||||
duration = 100.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
expiry = 200.u256,
|
||||
expiry = 200.uint64,
|
||||
collateralPerByte = 1.u256,
|
||||
)
|
||||
).tryGet
|
||||
|
||||
@ -3,6 +3,6 @@ import ../../helpers/mockclock
|
||||
|
||||
proc advanceToNextPeriod*(clock: MockClock, market: Market) {.async.} =
|
||||
let periodicity = await market.periodicity()
|
||||
let period = periodicity.periodOf(clock.now().u256)
|
||||
let period = periodicity.periodOf(clock.now().Timestamp)
|
||||
let periodEnd = periodicity.periodEnd(period)
|
||||
clock.set((periodEnd + 1).truncate(int))
|
||||
clock.set(periodEnd.toSecondsSince1970 + 1)
|
||||
|
||||
@ -14,7 +14,7 @@ import ../../helpers/mockclock
|
||||
|
||||
asyncchecksuite "sales state 'cancelled'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let clock = MockClock.new()
|
||||
|
||||
let currentCollateral = UInt256.example
|
||||
|
||||
@ -10,7 +10,7 @@ import ../../helpers
|
||||
|
||||
checksuite "sales state 'downloading'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
var state: SaleDownloading
|
||||
|
||||
setup:
|
||||
|
||||
@ -14,7 +14,7 @@ import ../../helpers/mockclock
|
||||
|
||||
asyncchecksuite "sales state 'errored'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let market = MockMarket.new()
|
||||
let clock = MockClock.new()
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ import ../../helpers
|
||||
|
||||
checksuite "sales state 'filled'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
|
||||
var market: MockMarket
|
||||
var slot: MockSlot
|
||||
|
||||
@ -9,7 +9,7 @@ import ../../helpers
|
||||
|
||||
checksuite "sales state 'filling'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
var state: SaleFilling
|
||||
|
||||
setup:
|
||||
|
||||
@ -15,7 +15,7 @@ import ../../helpers/mockclock
|
||||
|
||||
asyncchecksuite "sales state 'finished'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let clock = MockClock.new()
|
||||
|
||||
let currentCollateral = UInt256.example
|
||||
|
||||
@ -14,7 +14,7 @@ import ../../helpers/mockclock
|
||||
|
||||
asyncchecksuite "sales state 'ignored'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let market = MockMarket.new()
|
||||
let clock = MockClock.new()
|
||||
|
||||
|
||||
@ -20,7 +20,7 @@ import ../helpers/periods
|
||||
asyncchecksuite "sales state 'initialproving'":
|
||||
let proof = Groth16Proof.example
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let market = MockMarket.new()
|
||||
let clock = MockClock.new()
|
||||
|
||||
|
||||
@ -15,7 +15,7 @@ import ../../helpers/mockclock
|
||||
|
||||
asyncchecksuite "sales state 'payout'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let clock = MockClock.new()
|
||||
|
||||
let currentCollateral = UInt256.example
|
||||
|
||||
@ -22,7 +22,7 @@ import ../../helpers/mockclock
|
||||
|
||||
asyncchecksuite "sales state 'preparing'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let market = MockMarket.new()
|
||||
let clock = MockClock.new()
|
||||
var agent: SalesAgent
|
||||
@ -34,9 +34,9 @@ asyncchecksuite "sales state 'preparing'":
|
||||
|
||||
setup:
|
||||
availability = Availability.init(
|
||||
totalSize = request.ask.slotSize + 100.u256,
|
||||
freeSize = request.ask.slotSize + 100.u256,
|
||||
duration = request.ask.duration + 60.u256,
|
||||
totalSize = request.ask.slotSize + 100.uint64,
|
||||
freeSize = request.ask.slotSize + 100.uint64,
|
||||
duration = request.ask.duration + 60.uint64,
|
||||
minPricePerBytePerSecond = request.ask.pricePerBytePerSecond,
|
||||
totalCollateral = request.ask.collateralPerSlot * request.ask.slots.u256,
|
||||
)
|
||||
|
||||
@ -40,9 +40,9 @@ asyncchecksuite "sales state 'proving'":
|
||||
|
||||
proc advanceToNextPeriod(market: Market) {.async.} =
|
||||
let periodicity = await market.periodicity()
|
||||
let current = periodicity.periodOf(clock.now().u256)
|
||||
let current = periodicity.periodOf(clock.now().Timestamp)
|
||||
let periodEnd = periodicity.periodEnd(current)
|
||||
clock.set(periodEnd.truncate(int64) + 1)
|
||||
clock.set(periodEnd.toSecondsSince1970 + 1)
|
||||
|
||||
test "switches to cancelled state when request expires":
|
||||
let next = state.onCancelled(request)
|
||||
|
||||
@ -56,9 +56,9 @@ asyncchecksuite "sales state 'simulated-proving'":
|
||||
|
||||
proc advanceToNextPeriod(market: Market) {.async.} =
|
||||
let periodicity = await market.periodicity()
|
||||
let current = periodicity.periodOf(clock.now().u256)
|
||||
let current = periodicity.periodOf(clock.now().Timestamp)
|
||||
let periodEnd = periodicity.periodEnd(current)
|
||||
clock.set(periodEnd.truncate(int64) + 1)
|
||||
clock.set(periodEnd.toSecondsSince1970 + 1)
|
||||
|
||||
proc waitForProvingRounds(market: Market, rounds: int) {.async.} =
|
||||
var rnds = rounds - 1 # proof round runs prior to advancing
|
||||
|
||||
@ -19,7 +19,7 @@ import ../../helpers/mockclock
|
||||
|
||||
asyncchecksuite "sales state 'SlotReserving'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
var market: MockMarket
|
||||
var clock: MockClock
|
||||
var agent: SalesAgent
|
||||
|
||||
@ -16,7 +16,7 @@ import ../../helpers
|
||||
|
||||
checksuite "sales state 'unknown'":
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let slotIndex = request.ask.slots div 2
|
||||
let slotId = slotId(request.id, slotIndex)
|
||||
|
||||
var market: MockMarket
|
||||
|
||||
@ -41,17 +41,17 @@ asyncchecksuite "Reservations module":
|
||||
|
||||
proc createAvailability(): Availability =
|
||||
let example = Availability.example(collateralPerByte)
|
||||
let totalSize = rand(100000 .. 200000).u256
|
||||
let totalCollateral = totalSize * collateralPerByte
|
||||
let totalSize = rand(100000 .. 200000).uint64
|
||||
let totalCollateral = totalSize.u256 * collateralPerByte
|
||||
let availability = waitFor reservations.createAvailability(
|
||||
totalSize, example.duration, example.minPricePerBytePerSecond, totalCollateral
|
||||
)
|
||||
return availability.get
|
||||
|
||||
proc createReservation(availability: Availability): Reservation =
|
||||
let size = rand(1 ..< availability.freeSize.truncate(int))
|
||||
let size = rand(1 ..< availability.freeSize.int)
|
||||
let reservation = waitFor reservations.createReservation(
|
||||
availability.id, size.u256, RequestId.example, UInt256.example, 1.u256
|
||||
availability.id, size.uint64, RequestId.example, uint64.example, 1.u256
|
||||
)
|
||||
return reservation.get
|
||||
|
||||
@ -64,8 +64,8 @@ asyncchecksuite "Reservations module":
|
||||
check (await reservations.all(Availability)).get.len == 0
|
||||
|
||||
test "generates unique ids for storage availability":
|
||||
let availability1 = Availability.init(1.u256, 2.u256, 3.u256, 4.u256, 5.u256)
|
||||
let availability2 = Availability.init(1.u256, 2.u256, 3.u256, 4.u256, 5.u256)
|
||||
let availability1 = Availability.init(1.uint64, 2.uint64, 3.uint64, 4.u256, 5.u256)
|
||||
let availability2 = Availability.init(1.uint64, 2.uint64, 3.uint64, 4.u256, 5.u256)
|
||||
check availability1.id != availability2.id
|
||||
|
||||
test "can reserve available storage":
|
||||
@ -75,7 +75,7 @@ asyncchecksuite "Reservations module":
|
||||
test "creating availability reserves bytes in repo":
|
||||
let orig = repo.available.uint
|
||||
let availability = createAvailability()
|
||||
check repo.available.uint == (orig.u256 - availability.freeSize).truncate(uint)
|
||||
check repo.available.uint == orig - availability.freeSize
|
||||
|
||||
test "can get all availabilities":
|
||||
let availability1 = createAvailability()
|
||||
@ -129,7 +129,7 @@ asyncchecksuite "Reservations module":
|
||||
test "cannot create reservation with non-existant availability":
|
||||
let availability = Availability.example
|
||||
let created = await reservations.createReservation(
|
||||
availability.id, UInt256.example, RequestId.example, UInt256.example, 1.u256
|
||||
availability.id, uint64.example, RequestId.example, uint64.example, 1.u256
|
||||
)
|
||||
check created.isErr
|
||||
check created.error of NotExistsError
|
||||
@ -140,7 +140,7 @@ asyncchecksuite "Reservations module":
|
||||
availability.id,
|
||||
availability.totalSize + 1,
|
||||
RequestId.example,
|
||||
UInt256.example,
|
||||
uint64.example,
|
||||
UInt256.example,
|
||||
)
|
||||
check created.isErr
|
||||
@ -153,12 +153,12 @@ asyncchecksuite "Reservations module":
|
||||
availability.id,
|
||||
availability.totalSize - 1,
|
||||
RequestId.example,
|
||||
UInt256.example,
|
||||
uint64.example,
|
||||
UInt256.example,
|
||||
)
|
||||
|
||||
let two = reservations.createReservation(
|
||||
availability.id, availability.totalSize, RequestId.example, UInt256.example,
|
||||
availability.id, availability.totalSize, RequestId.example, uint64.example,
|
||||
UInt256.example,
|
||||
)
|
||||
|
||||
@ -228,7 +228,7 @@ asyncchecksuite "Reservations module":
|
||||
let reservation = createReservation(availability)
|
||||
let orig = availability.freeSize - reservation.size
|
||||
let origQuota = repo.quotaReservedBytes
|
||||
let returnedBytes = reservation.size + 200.u256
|
||||
let returnedBytes = reservation.size + 200.uint64
|
||||
|
||||
check isOk await reservations.returnBytesToAvailability(
|
||||
reservation.availabilityId, reservation.id, returnedBytes
|
||||
@ -238,7 +238,7 @@ asyncchecksuite "Reservations module":
|
||||
let updated = !(await reservations.get(key, Availability))
|
||||
|
||||
check updated.freeSize > orig
|
||||
check (updated.freeSize - orig) == 200.u256
|
||||
check (updated.freeSize - orig) == 200.uint64
|
||||
check (repo.quotaReservedBytes - origQuota) == 200.NBytes
|
||||
|
||||
test "update releases quota when lowering size":
|
||||
@ -271,14 +271,14 @@ asyncchecksuite "Reservations module":
|
||||
let availability = createAvailability()
|
||||
let reservation = createReservation(availability)
|
||||
let updated = await reservations.release(
|
||||
reservation.id, reservation.availabilityId, (reservation.size + 1).truncate(uint)
|
||||
reservation.id, reservation.availabilityId, reservation.size + 1
|
||||
)
|
||||
check updated.isErr
|
||||
check updated.error of BytesOutOfBoundsError
|
||||
|
||||
test "cannot release bytes from non-existant reservation":
|
||||
let availability = createAvailability()
|
||||
let reservation = createReservation(availability)
|
||||
discard createReservation(availability)
|
||||
let updated = await reservations.release(ReservationId.example, availability.id, 1)
|
||||
check updated.isErr
|
||||
check updated.error of NotExistsError
|
||||
@ -297,7 +297,7 @@ asyncchecksuite "Reservations module":
|
||||
var added: Availability
|
||||
reservations.onAvailabilityAdded = proc(a: Availability) {.async.} =
|
||||
added = a
|
||||
availability.freeSize += 1.u256
|
||||
availability.freeSize += 1
|
||||
discard await reservations.update(availability)
|
||||
|
||||
check added == availability
|
||||
@ -307,7 +307,7 @@ asyncchecksuite "Reservations module":
|
||||
var called = false
|
||||
reservations.onAvailabilityAdded = proc(a: Availability) {.async.} =
|
||||
called = true
|
||||
availability.freeSize -= 1.u256
|
||||
availability.freeSize -= 1
|
||||
discard await reservations.update(availability)
|
||||
|
||||
check not called
|
||||
@ -356,14 +356,11 @@ asyncchecksuite "Reservations module":
|
||||
check reservations.hasAvailable(DefaultQuotaBytes.uint - 1)
|
||||
|
||||
test "reports quota not available to be reserved":
|
||||
check not reservations.hasAvailable(DefaultQuotaBytes.uint + 1)
|
||||
check not reservations.hasAvailable(DefaultQuotaBytes.uint64 + 1)
|
||||
|
||||
test "fails to create availability with size that is larger than available quota":
|
||||
let created = await reservations.createAvailability(
|
||||
(DefaultQuotaBytes.uint + 1).u256,
|
||||
UInt256.example,
|
||||
UInt256.example,
|
||||
UInt256.example,
|
||||
DefaultQuotaBytes.uint64 + 1, uint64.example, UInt256.example, UInt256.example
|
||||
)
|
||||
check created.isErr
|
||||
check created.error of ReserveFailedError
|
||||
|
||||
@ -42,15 +42,15 @@ asyncchecksuite "Sales - start":
|
||||
request = StorageRequest(
|
||||
ask: StorageAsk(
|
||||
slots: 4,
|
||||
slotSize: 100.u256,
|
||||
duration: 60.u256,
|
||||
slotSize: 100.uint64,
|
||||
duration: 60.uint64,
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
collateralPerByte: 1.u256,
|
||||
),
|
||||
content: StorageContent(
|
||||
cid: Cid.init("zb2rhheVmk3bLks5MgzTqyznLu1zqGH5jrfTA1eAZXrjx7Vob").tryGet
|
||||
),
|
||||
expiry: (getTime() + initDuration(hours = 1)).toUnix.u256,
|
||||
expiry: (getTime() + initDuration(hours = 1)).toUnix.uint64,
|
||||
)
|
||||
|
||||
market = MockMarket.new()
|
||||
@ -62,7 +62,7 @@ asyncchecksuite "Sales - start":
|
||||
sales = Sales.new(market, clock, repo)
|
||||
reservations = sales.context.reservations
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
return success()
|
||||
|
||||
@ -78,7 +78,7 @@ asyncchecksuite "Sales - start":
|
||||
return success(proof)
|
||||
itemsProcessed = @[]
|
||||
expiry = (clock.now() + 42)
|
||||
request.expiry = expiry.u256
|
||||
request.expiry = expiry.uint64
|
||||
|
||||
teardown:
|
||||
await sales.stop()
|
||||
@ -86,7 +86,7 @@ asyncchecksuite "Sales - start":
|
||||
await repoTmp.destroyDb()
|
||||
await metaTmp.destroyDb()
|
||||
|
||||
proc fillSlot(slotIdx: UInt256 = 0.u256) {.async.} =
|
||||
proc fillSlot(slotIdx: uint64 = 0.uint64) {.async.} =
|
||||
let address = await market.getSigner()
|
||||
let slot =
|
||||
MockSlot(requestId: request.id, slotIndex: slotIdx, proof: proof, host: address)
|
||||
@ -101,15 +101,13 @@ asyncchecksuite "Sales - start":
|
||||
market.requestState[request.id] = RequestState.New
|
||||
market.requestExpiry[request.id] = expiry
|
||||
|
||||
let slot0 =
|
||||
MockSlot(requestId: request.id, slotIndex: 0.u256, proof: proof, host: me)
|
||||
let slot0 = MockSlot(requestId: request.id, slotIndex: 0, proof: proof, host: me)
|
||||
await fillSlot(slot0.slotIndex)
|
||||
|
||||
let slot1 =
|
||||
MockSlot(requestId: request.id, slotIndex: 1.u256, proof: proof, host: me)
|
||||
let slot1 = MockSlot(requestId: request.id, slotIndex: 1, proof: proof, host: me)
|
||||
await fillSlot(slot1.slotIndex)
|
||||
|
||||
market.activeSlots[me] = @[request.slotId(0.u256), request.slotId(1.u256)]
|
||||
market.activeSlots[me] = @[request.slotId(0), request.slotId(1)]
|
||||
market.requested = @[request]
|
||||
market.activeRequests[me] = @[request.id]
|
||||
|
||||
@ -117,10 +115,10 @@ asyncchecksuite "Sales - start":
|
||||
|
||||
check eventually sales.agents.len == 2
|
||||
check sales.agents.any(
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.u256
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.uint64
|
||||
)
|
||||
check sales.agents.any(
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.u256
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.uint64
|
||||
)
|
||||
|
||||
asyncchecksuite "Sales":
|
||||
@ -129,7 +127,7 @@ asyncchecksuite "Sales":
|
||||
repoTmp = TempLevelDb.new()
|
||||
metaTmp = TempLevelDb.new()
|
||||
|
||||
var totalAvailabilitySize: UInt256
|
||||
var totalAvailabilitySize: uint64
|
||||
var minPricePerBytePerSecond: UInt256
|
||||
var requestedCollateralPerByte: UInt256
|
||||
var totalCollateral: UInt256
|
||||
@ -144,29 +142,29 @@ asyncchecksuite "Sales":
|
||||
var itemsProcessed: seq[SlotQueueItem]
|
||||
|
||||
setup:
|
||||
totalAvailabilitySize = 100.u256
|
||||
totalAvailabilitySize = 100.uint64
|
||||
minPricePerBytePerSecond = 1.u256
|
||||
requestedCollateralPerByte = 1.u256
|
||||
totalCollateral = requestedCollateralPerByte * totalAvailabilitySize
|
||||
totalCollateral = requestedCollateralPerByte * totalAvailabilitySize.stuint(256)
|
||||
availability = Availability.init(
|
||||
totalSize = totalAvailabilitySize,
|
||||
freeSize = totalAvailabilitySize,
|
||||
duration = 60.u256,
|
||||
duration = 60.uint64,
|
||||
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
totalCollateral = totalCollateral,
|
||||
)
|
||||
request = StorageRequest(
|
||||
ask: StorageAsk(
|
||||
slots: 4,
|
||||
slotSize: 100.u256,
|
||||
duration: 60.u256,
|
||||
slotSize: 100.uint64,
|
||||
duration: 60.uint64,
|
||||
pricePerBytePerSecond: minPricePerBytePerSecond,
|
||||
collateralPerByte: 1.u256,
|
||||
),
|
||||
content: StorageContent(
|
||||
cid: Cid.init("zb2rhheVmk3bLks5MgzTqyznLu1zqGH5jrfTA1eAZXrjx7Vob").tryGet
|
||||
),
|
||||
expiry: (getTime() + initDuration(hours = 1)).toUnix.u256,
|
||||
expiry: (getTime() + initDuration(hours = 1)).toUnix.uint64,
|
||||
)
|
||||
|
||||
market = MockMarket.new()
|
||||
@ -183,7 +181,7 @@ asyncchecksuite "Sales":
|
||||
sales = Sales.new(market, clock, repo)
|
||||
reservations = sales.context.reservations
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
return success()
|
||||
|
||||
@ -288,13 +286,13 @@ asyncchecksuite "Sales":
|
||||
|
||||
test "removes slot index from slot queue once SlotFilled emitted":
|
||||
let request1 = await addRequestToSaturatedQueue()
|
||||
market.emitSlotFilled(request1.id, 1.u256)
|
||||
market.emitSlotFilled(request1.id, 1.uint64)
|
||||
let expected = SlotQueueItem.init(request1, 1'u16)
|
||||
check always (not itemsProcessed.contains(expected))
|
||||
|
||||
test "removes slot index from slot queue once SlotReservationsFull emitted":
|
||||
let request1 = await addRequestToSaturatedQueue()
|
||||
market.emitSlotReservationsFull(request1.id, 1.u256)
|
||||
market.emitSlotReservationsFull(request1.id, 1.uint64)
|
||||
let expected = SlotQueueItem.init(request1, 1'u16)
|
||||
check always (not itemsProcessed.contains(expected))
|
||||
|
||||
@ -305,7 +303,7 @@ asyncchecksuite "Sales":
|
||||
|
||||
createAvailability()
|
||||
market.requested.add request # "contract" must be able to return request
|
||||
market.emitSlotFreed(request.id, 2.u256)
|
||||
market.emitSlotFreed(request.id, 2.uint64)
|
||||
|
||||
let expected = SlotQueueItem.init(request, 2.uint16)
|
||||
check eventually itemsProcessed.contains(expected)
|
||||
@ -350,10 +348,10 @@ asyncchecksuite "Sales":
|
||||
|
||||
test "availability size is reduced by request slot size when fully downloaded":
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
let blk = bt.Block.new(@[1.byte]).get
|
||||
await onBatch(blk.repeat(request.ask.slotSize.truncate(int)))
|
||||
await onBatch(blk.repeat(request.ask.slotSize.int))
|
||||
|
||||
createAvailability()
|
||||
await market.requestStorage(request)
|
||||
@ -361,16 +359,16 @@ asyncchecksuite "Sales":
|
||||
availability.freeSize - request.ask.slotSize
|
||||
|
||||
test "non-downloaded bytes are returned to availability once finished":
|
||||
var slotIndex = 0.u256
|
||||
var slotIndex = 0.uint64
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
slotIndex = slot
|
||||
let blk = bt.Block.new(@[1.byte]).get
|
||||
await onBatch(@[blk])
|
||||
|
||||
let sold = newFuture[void]()
|
||||
sales.onSale = proc(request: StorageRequest, slotIndex: UInt256) =
|
||||
sales.onSale = proc(request: StorageRequest, slotIndex: uint64) =
|
||||
sold.complete()
|
||||
|
||||
createAvailability()
|
||||
@ -381,7 +379,7 @@ asyncchecksuite "Sales":
|
||||
|
||||
# complete request
|
||||
market.slotState[request.slotId(slotIndex)] = SlotState.Finished
|
||||
clock.advance(request.ask.duration.truncate(int64))
|
||||
clock.advance(request.ask.duration.int64)
|
||||
|
||||
check eventually getAvailability().freeSize == origSize - 1
|
||||
|
||||
@ -413,17 +411,17 @@ asyncchecksuite "Sales":
|
||||
test "ignores request when slot state is not free":
|
||||
createAvailability()
|
||||
await market.requestStorage(request)
|
||||
market.slotState[request.slotId(0.u256)] = SlotState.Filled
|
||||
market.slotState[request.slotId(1.u256)] = SlotState.Filled
|
||||
market.slotState[request.slotId(2.u256)] = SlotState.Filled
|
||||
market.slotState[request.slotId(3.u256)] = SlotState.Filled
|
||||
market.slotState[request.slotId(0.uint64)] = SlotState.Filled
|
||||
market.slotState[request.slotId(1.uint64)] = SlotState.Filled
|
||||
market.slotState[request.slotId(2.uint64)] = SlotState.Filled
|
||||
market.slotState[request.slotId(3.uint64)] = SlotState.Filled
|
||||
check wasIgnored()
|
||||
|
||||
test "retrieves and stores data locally":
|
||||
var storingRequest: StorageRequest
|
||||
var storingSlot: UInt256
|
||||
var storingSlot: uint64
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
storingRequest = request
|
||||
storingSlot = slot
|
||||
@ -431,12 +429,12 @@ asyncchecksuite "Sales":
|
||||
createAvailability()
|
||||
await market.requestStorage(request)
|
||||
check eventually storingRequest == request
|
||||
check storingSlot < request.ask.slots.u256
|
||||
check storingSlot < request.ask.slots
|
||||
|
||||
test "makes storage available again when data retrieval fails":
|
||||
let error = newException(IOError, "data retrieval failed")
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
return failure(error)
|
||||
createAvailability()
|
||||
@ -445,7 +443,7 @@ asyncchecksuite "Sales":
|
||||
|
||||
test "generates proof of storage":
|
||||
var provingRequest: StorageRequest
|
||||
var provingSlot: UInt256
|
||||
var provingSlot: uint64
|
||||
sales.onProve = proc(
|
||||
slot: Slot, challenge: ProofChallenge
|
||||
): Future[?!Groth16Proof] {.async.} =
|
||||
@ -457,7 +455,7 @@ asyncchecksuite "Sales":
|
||||
await allowRequestToStart()
|
||||
|
||||
check eventually provingRequest == request
|
||||
check provingSlot < request.ask.slots.u256
|
||||
check provingSlot < request.ask.slots
|
||||
|
||||
test "fills a slot":
|
||||
createAvailability()
|
||||
@ -466,14 +464,14 @@ asyncchecksuite "Sales":
|
||||
|
||||
check eventually market.filled.len > 0
|
||||
check market.filled[0].requestId == request.id
|
||||
check market.filled[0].slotIndex < request.ask.slots.u256
|
||||
check market.filled[0].slotIndex < request.ask.slots
|
||||
check market.filled[0].proof == proof
|
||||
check market.filled[0].host == await market.getSigner()
|
||||
|
||||
test "calls onFilled when slot is filled":
|
||||
var soldRequest = StorageRequest.default
|
||||
var soldSlotIndex = UInt256.high
|
||||
sales.onSale = proc(request: StorageRequest, slotIndex: UInt256) =
|
||||
var soldSlotIndex = uint64.high
|
||||
sales.onSale = proc(request: StorageRequest, slotIndex: uint64) =
|
||||
soldRequest = request
|
||||
soldSlotIndex = slotIndex
|
||||
createAvailability()
|
||||
@ -481,7 +479,7 @@ asyncchecksuite "Sales":
|
||||
await allowRequestToStart()
|
||||
|
||||
check eventually soldRequest == request
|
||||
check soldSlotIndex < request.ask.slots.u256
|
||||
check soldSlotIndex < request.ask.slots
|
||||
|
||||
test "calls onClear when storage becomes available again":
|
||||
# fail the proof intentionally to trigger `agent.finish(success=false)`,
|
||||
@ -491,8 +489,8 @@ asyncchecksuite "Sales":
|
||||
): Future[?!Groth16Proof] {.async.} =
|
||||
raise newException(IOError, "proof failed")
|
||||
var clearedRequest: StorageRequest
|
||||
var clearedSlotIndex: UInt256
|
||||
sales.onClear = proc(request: StorageRequest, slotIndex: UInt256) =
|
||||
var clearedSlotIndex: uint64
|
||||
sales.onClear = proc(request: StorageRequest, slotIndex: uint64) =
|
||||
clearedRequest = request
|
||||
clearedSlotIndex = slotIndex
|
||||
createAvailability()
|
||||
@ -500,19 +498,19 @@ asyncchecksuite "Sales":
|
||||
await allowRequestToStart()
|
||||
|
||||
check eventually clearedRequest == request
|
||||
check clearedSlotIndex < request.ask.slots.u256
|
||||
check clearedSlotIndex < request.ask.slots
|
||||
|
||||
test "makes storage available again when other host fills the slot":
|
||||
let otherHost = Address.example
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
await sleepAsync(chronos.hours(1))
|
||||
return success()
|
||||
createAvailability()
|
||||
await market.requestStorage(request)
|
||||
for slotIndex in 0 ..< request.ask.slots:
|
||||
market.fillSlot(request.id, slotIndex.u256, proof, otherHost)
|
||||
market.fillSlot(request.id, slotIndex.uint64, proof, otherHost)
|
||||
check eventually (await reservations.all(Availability)).get == @[availability]
|
||||
|
||||
test "makes storage available again when request expires":
|
||||
@ -521,7 +519,7 @@ asyncchecksuite "Sales":
|
||||
|
||||
let origSize = availability.freeSize
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
await sleepAsync(chronos.hours(1))
|
||||
return success()
|
||||
@ -541,12 +539,12 @@ asyncchecksuite "Sales":
|
||||
# ensure only one slot, otherwise once bytes are returned to the
|
||||
# availability, the queue will be unpaused and availability will be consumed
|
||||
# by other slots
|
||||
request.ask.slots = 1.uint64
|
||||
request.ask.slots = 1
|
||||
market.requestExpiry[request.id] = expiry
|
||||
|
||||
let origSize = availability.freeSize
|
||||
sales.onStore = proc(
|
||||
request: StorageRequest, slot: UInt256, onBatch: BatchProc
|
||||
request: StorageRequest, slot: uint64, onBatch: BatchProc
|
||||
): Future[?!void] {.async.} =
|
||||
await sleepAsync(chronos.hours(1))
|
||||
return success()
|
||||
@ -573,21 +571,19 @@ asyncchecksuite "Sales":
|
||||
market.requestState[request.id] = RequestState.New
|
||||
market.requestEnds[request.id] = request.expiry.toSecondsSince1970
|
||||
|
||||
proc fillSlot(slotIdx: UInt256 = 0.u256) {.async.} =
|
||||
proc fillSlot(slotIdx: uint64 = 0) {.async.} =
|
||||
let address = await market.getSigner()
|
||||
let slot =
|
||||
MockSlot(requestId: request.id, slotIndex: slotIdx, proof: proof, host: address)
|
||||
market.filled.add slot
|
||||
market.slotState[slotId(request.id, slotIdx)] = SlotState.Filled
|
||||
|
||||
let slot0 =
|
||||
MockSlot(requestId: request.id, slotIndex: 0.u256, proof: proof, host: me)
|
||||
let slot0 = MockSlot(requestId: request.id, slotIndex: 0, proof: proof, host: me)
|
||||
await fillSlot(slot0.slotIndex)
|
||||
|
||||
let slot1 =
|
||||
MockSlot(requestId: request.id, slotIndex: 1.u256, proof: proof, host: me)
|
||||
let slot1 = MockSlot(requestId: request.id, slotIndex: 1, proof: proof, host: me)
|
||||
await fillSlot(slot1.slotIndex)
|
||||
market.activeSlots[me] = @[request.slotId(0.u256), request.slotId(1.u256)]
|
||||
market.activeSlots[me] = @[request.slotId(0), request.slotId(1)]
|
||||
market.requested = @[request]
|
||||
market.activeRequests[me] = @[request.id]
|
||||
|
||||
@ -595,16 +591,16 @@ asyncchecksuite "Sales":
|
||||
|
||||
check eventually sales.agents.len == 2
|
||||
check sales.agents.any(
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.u256
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 0.uint64
|
||||
)
|
||||
check sales.agents.any(
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.u256
|
||||
agent => agent.data.requestId == request.id and agent.data.slotIndex == 1.uint64
|
||||
)
|
||||
|
||||
test "deletes inactive reservations on load":
|
||||
createAvailability()
|
||||
discard await reservations.createReservation(
|
||||
availability.id, 100.u256, RequestId.example, UInt256.example, UInt256.example
|
||||
availability.id, 100.uint64, RequestId.example, 0.uint64, UInt256.example
|
||||
)
|
||||
check (await reservations.all(Reservation)).get.len == 1
|
||||
await sales.load()
|
||||
|
||||
@ -27,7 +27,7 @@ method onFailed*(state: MockState, request: StorageRequest): ?State =
|
||||
onFailedCalled = true
|
||||
|
||||
method onSlotFilled*(
|
||||
state: MockState, requestId: RequestId, slotIndex: UInt256
|
||||
state: MockState, requestId: RequestId, slotIndex: uint64
|
||||
): ?State =
|
||||
onSlotFilledCalled = true
|
||||
|
||||
@ -35,17 +35,16 @@ asyncchecksuite "Sales agent":
|
||||
let request = StorageRequest.example
|
||||
var agent: SalesAgent
|
||||
var context: SalesContext
|
||||
var slotIndex: UInt256
|
||||
var slotIndex: uint64
|
||||
var market: MockMarket
|
||||
var clock: MockClock
|
||||
|
||||
setup:
|
||||
market = MockMarket.new()
|
||||
market.requestExpiry[request.id] =
|
||||
getTime().toUnix() + request.expiry.truncate(int64)
|
||||
market.requestExpiry[request.id] = getTime().toUnix() + request.expiry.int64
|
||||
clock = MockClock.new()
|
||||
context = SalesContext(market: market, clock: clock)
|
||||
slotIndex = 0.u256
|
||||
slotIndex = 0.uint64
|
||||
onCancelCalled = false
|
||||
onFailedCalled = false
|
||||
onSlotFilledCalled = false
|
||||
|
||||
@ -146,18 +146,18 @@ suite "Slot queue":
|
||||
|
||||
test "correctly compares SlotQueueItems":
|
||||
var requestA = StorageRequest.example
|
||||
requestA.ask.duration = 1.u256
|
||||
requestA.ask.duration = 1.uint64
|
||||
requestA.ask.pricePerBytePerSecond = 1.u256
|
||||
check requestA.ask.pricePerSlot == 1.u256 * requestA.ask.slotSize
|
||||
check requestA.ask.pricePerSlot == 1.u256 * requestA.ask.slotSize.u256
|
||||
requestA.ask.collateralPerByte = 100000.u256
|
||||
requestA.expiry = 1001.u256
|
||||
requestA.expiry = 1001.uint64
|
||||
|
||||
var requestB = StorageRequest.example
|
||||
requestB.ask.duration = 100.u256
|
||||
requestB.ask.duration = 100.uint64
|
||||
requestB.ask.pricePerBytePerSecond = 1000.u256
|
||||
check requestB.ask.pricePerSlot == 100000.u256 * requestB.ask.slotSize
|
||||
check requestB.ask.pricePerSlot == 100000.u256 * requestB.ask.slotSize.u256
|
||||
requestB.ask.collateralPerByte = 1.u256
|
||||
requestB.expiry = 1000.u256
|
||||
requestB.expiry = 1000.uint64
|
||||
|
||||
let itemA = SlotQueueItem.init(requestA, 0)
|
||||
let itemB = SlotQueueItem.init(requestB, 0)
|
||||
@ -169,21 +169,21 @@ suite "Slot queue":
|
||||
let itemA = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256,
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64,
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 2.u256, # profitability is higher (good)
|
||||
collateralPerByte: 1.u256,
|
||||
expiry: 1.u256,
|
||||
expiry: 1.uint64,
|
||||
seen: true, # seen (bad), more weight than profitability
|
||||
)
|
||||
let itemB = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256,
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64,
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256, # profitability is lower (bad)
|
||||
collateralPerByte: 1.u256,
|
||||
expiry: 1.u256,
|
||||
expiry: 1.uint64,
|
||||
seen: false, # not seen (good)
|
||||
)
|
||||
check itemB.toSlotQueueItem < itemA.toSlotQueueItem # B higher priority than A
|
||||
@ -194,22 +194,22 @@ suite "Slot queue":
|
||||
let itemA = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256,
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64,
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256, # reward is lower (bad)
|
||||
collateralPerByte: 1.u256, # collateral is lower (good)
|
||||
expiry: 1.u256,
|
||||
expiry: 1.uint64,
|
||||
seen: false,
|
||||
)
|
||||
let itemB = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256,
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64,
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 2.u256,
|
||||
# reward is higher (good), more weight than collateral
|
||||
collateralPerByte: 2.u256, # collateral is higher (bad)
|
||||
expiry: 1.u256,
|
||||
expiry: 1.uint64,
|
||||
seen: false,
|
||||
)
|
||||
|
||||
@ -220,21 +220,21 @@ suite "Slot queue":
|
||||
let itemA = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256,
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64,
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
collateralPerByte: 2.u256, # collateral is higher (bad)
|
||||
expiry: 2.u256, # expiry is longer (good)
|
||||
expiry: 2.uint64, # expiry is longer (good)
|
||||
seen: false,
|
||||
)
|
||||
let itemB = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256,
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64,
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
collateralPerByte: 1.u256, # collateral is lower (good), more weight than expiry
|
||||
expiry: 1.u256, # expiry is shorter (bad)
|
||||
expiry: 1.uint64, # expiry is shorter (bad)
|
||||
seen: false,
|
||||
)
|
||||
|
||||
@ -245,21 +245,21 @@ suite "Slot queue":
|
||||
let itemA = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256, # slotSize is smaller (good)
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64, # slotSize is smaller (good)
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
collateralPerByte: 1.u256,
|
||||
expiry: 1.u256, # expiry is shorter (bad)
|
||||
expiry: 1.uint64, # expiry is shorter (bad)
|
||||
seen: false,
|
||||
)
|
||||
let itemB = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 2.u256, # slotSize is larger (bad)
|
||||
duration: 1.u256,
|
||||
slotSize: 2.uint64, # slotSize is larger (bad)
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
collateralPerByte: 1.u256,
|
||||
expiry: 2.u256, # expiry is longer (good), more weight than slotSize
|
||||
expiry: 2.uint64, # expiry is longer (good), more weight than slotSize
|
||||
seen: false,
|
||||
)
|
||||
|
||||
@ -270,21 +270,21 @@ suite "Slot queue":
|
||||
let itemA = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 2.u256, # slotSize is larger (bad)
|
||||
duration: 1.u256,
|
||||
slotSize: 2.uint64, # slotSize is larger (bad)
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
collateralPerByte: 1.u256,
|
||||
expiry: 1.u256, # expiry is shorter (bad)
|
||||
expiry: 1.uint64, # expiry is shorter (bad)
|
||||
seen: false,
|
||||
)
|
||||
let itemB = MockSlotQueueItem(
|
||||
requestId: request.id,
|
||||
slotIndex: 0,
|
||||
slotSize: 1.u256, # slotSize is smaller (good)
|
||||
duration: 1.u256,
|
||||
slotSize: 1.uint64, # slotSize is smaller (good)
|
||||
duration: 1.uint64,
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
collateralPerByte: 1.u256,
|
||||
expiry: 1.u256,
|
||||
expiry: 1.uint64,
|
||||
seen: false,
|
||||
)
|
||||
|
||||
@ -460,14 +460,14 @@ suite "Slot queue":
|
||||
test "sorts items by expiry descending (longer expiry = higher priority)":
|
||||
var request = StorageRequest.example
|
||||
let item0 = SlotQueueItem.init(request, 0)
|
||||
request.expiry += 1.u256
|
||||
request.expiry += 1
|
||||
let item1 = SlotQueueItem.init(request, 1)
|
||||
check item1 < item0
|
||||
|
||||
test "sorts items by slot size descending (bigger dataset = higher profitability = higher priority)":
|
||||
var request = StorageRequest.example
|
||||
let item0 = SlotQueueItem.init(request, 0)
|
||||
request.ask.slotSize += 1.u256
|
||||
request.ask.slotSize += 1
|
||||
let item1 = SlotQueueItem.init(request, 1)
|
||||
check item1 < item0
|
||||
|
||||
|
||||
@ -28,8 +28,8 @@ asyncchecksuite "Purchasing":
|
||||
request = StorageRequest(
|
||||
ask: StorageAsk(
|
||||
slots: uint8.example.uint64,
|
||||
slotSize: uint32.example.u256,
|
||||
duration: uint16.example.u256,
|
||||
slotSize: uint32.example.uint64,
|
||||
duration: uint16.example.uint64,
|
||||
pricePerBytePerSecond: uint8.example.u256,
|
||||
)
|
||||
)
|
||||
@ -100,7 +100,6 @@ asyncchecksuite "Purchasing":
|
||||
market.requestExpiry[populatedRequest.id] = expiry
|
||||
let purchase = await purchasing.purchase(populatedRequest)
|
||||
check eventually market.requested.len > 0
|
||||
let request = market.requested[0]
|
||||
|
||||
clock.set(expiry + 1)
|
||||
expect PurchaseTimeout:
|
||||
@ -130,8 +129,8 @@ checksuite "Purchasing state machine":
|
||||
request = StorageRequest(
|
||||
ask: StorageAsk(
|
||||
slots: uint8.example.uint64,
|
||||
slotSize: uint32.example.u256,
|
||||
duration: uint16.example.u256,
|
||||
slotSize: uint32.example.uint64,
|
||||
duration: uint16.example.uint64,
|
||||
pricePerBytePerSecond: uint8.example.u256,
|
||||
)
|
||||
)
|
||||
@ -185,7 +184,7 @@ checksuite "Purchasing state machine":
|
||||
test "moves to PurchaseStarted when request state is Started":
|
||||
let request = StorageRequest.example
|
||||
let purchase = Purchase.new(request, market, clock)
|
||||
market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64)
|
||||
market.requestEnds[request.id] = clock.now() + request.ask.duration.int64
|
||||
market.requested = @[request]
|
||||
market.requestState[request.id] = RequestState.Started
|
||||
let next = await PurchaseUnknown().run(purchase)
|
||||
@ -218,7 +217,7 @@ checksuite "Purchasing state machine":
|
||||
test "moves to PurchaseFailed state once RequestFailed emitted":
|
||||
let request = StorageRequest.example
|
||||
let purchase = Purchase.new(request, market, clock)
|
||||
market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64)
|
||||
market.requestEnds[request.id] = clock.now() + request.ask.duration.int64
|
||||
let future = PurchaseStarted().run(purchase)
|
||||
|
||||
market.emitRequestFailed(request.id)
|
||||
@ -229,10 +228,10 @@ checksuite "Purchasing state machine":
|
||||
test "moves to PurchaseFinished state once request finishes":
|
||||
let request = StorageRequest.example
|
||||
let purchase = Purchase.new(request, market, clock)
|
||||
market.requestEnds[request.id] = clock.now() + request.ask.duration.truncate(int64)
|
||||
market.requestEnds[request.id] = clock.now() + request.ask.duration.int64
|
||||
let future = PurchaseStarted().run(purchase)
|
||||
|
||||
clock.advance(request.ask.duration.truncate(int64) + 1)
|
||||
clock.advance(request.ask.duration.int64 + 1)
|
||||
|
||||
let next = await future
|
||||
check !next of PurchaseFinished
|
||||
|
||||
@ -16,8 +16,8 @@ logScope:
|
||||
topics = "testValidation"
|
||||
|
||||
asyncchecksuite "validation":
|
||||
let period = 10
|
||||
let timeout = 5
|
||||
let period = 10.uint64
|
||||
let timeout = 5.uint64
|
||||
let maxSlots = MaxSlots(100)
|
||||
let validationGroups = ValidationGroups(8).some
|
||||
let slot = Slot.example
|
||||
@ -51,8 +51,8 @@ asyncchecksuite "validation":
|
||||
groupIndex = groupIndexForSlotId(slot.id, !validationGroups)
|
||||
clock = MockClock.new()
|
||||
market = MockMarket.new(clock = Clock(clock).some)
|
||||
market.config.proofs.period = period.u256
|
||||
market.config.proofs.timeout = timeout.u256
|
||||
market.config.proofs.period = period
|
||||
market.config.proofs.timeout = timeout
|
||||
validation = newValidation(clock, market, maxSlots, validationGroups, groupIndex)
|
||||
|
||||
teardown:
|
||||
@ -60,10 +60,10 @@ asyncchecksuite "validation":
|
||||
await validation.stop()
|
||||
|
||||
proc advanceToNextPeriod() =
|
||||
let periodicity = Periodicity(seconds: period.u256)
|
||||
let period = periodicity.periodOf(clock.now().u256)
|
||||
let periodicity = Periodicity(seconds: period)
|
||||
let period = periodicity.periodOf(clock.now().Timestamp)
|
||||
let periodEnd = periodicity.periodEnd(period)
|
||||
clock.set((periodEnd + 1).truncate(int))
|
||||
clock.set(periodEnd.toSecondsSince1970 + 1)
|
||||
|
||||
test "the list of slots that it's monitoring is empty initially":
|
||||
check validation.slots.len == 0
|
||||
|
||||
@ -49,28 +49,29 @@ ethersuite "Marketplace contracts":
|
||||
switchAccount(host)
|
||||
discard
|
||||
await token.approve(marketplace.address, request.ask.collateralPerSlot).confirm(1)
|
||||
discard await marketplace.reserveSlot(request.id, 0.u256).confirm(1)
|
||||
let receipt = await marketplace.fillSlot(request.id, 0.u256, proof).confirm(1)
|
||||
discard await marketplace.reserveSlot(request.id, 0.uint64).confirm(1)
|
||||
let receipt = await marketplace.fillSlot(request.id, 0.uint64, proof).confirm(1)
|
||||
filledAt = await ethProvider.blockTime(BlockTag.init(!receipt.blockNumber))
|
||||
slotId = request.slotId(0.u256)
|
||||
slotId = request.slotId(0.uint64)
|
||||
|
||||
proc waitUntilProofRequired(slotId: SlotId) {.async.} =
|
||||
let currentPeriod = periodicity.periodOf(await ethProvider.currentTime())
|
||||
await ethProvider.advanceTimeTo(periodicity.periodEnd(currentPeriod))
|
||||
let currentPeriod =
|
||||
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
await ethProvider.advanceTimeTo(periodicity.periodEnd(currentPeriod).u256)
|
||||
while not (
|
||||
(await marketplace.isProofRequired(slotId)) and
|
||||
(await marketplace.getPointer(slotId)) < 250
|
||||
)
|
||||
:
|
||||
await ethProvider.advanceTime(periodicity.seconds)
|
||||
await ethProvider.advanceTime(periodicity.seconds.u256)
|
||||
|
||||
proc startContract() {.async.} =
|
||||
for slotIndex in 1 ..< request.ask.slots:
|
||||
discard await token
|
||||
.approve(marketplace.address, request.ask.collateralPerSlot)
|
||||
.confirm(1)
|
||||
discard await marketplace.reserveSlot(request.id, slotIndex.u256).confirm(1)
|
||||
discard await marketplace.fillSlot(request.id, slotIndex.u256, proof).confirm(1)
|
||||
discard await marketplace.reserveSlot(request.id, slotIndex.uint64).confirm(1)
|
||||
discard await marketplace.fillSlot(request.id, slotIndex.uint64, proof).confirm(1)
|
||||
|
||||
test "accept marketplace proofs":
|
||||
switchAccount(host)
|
||||
@ -80,9 +81,10 @@ ethersuite "Marketplace contracts":
|
||||
test "can mark missing proofs":
|
||||
switchAccount(host)
|
||||
await waitUntilProofRequired(slotId)
|
||||
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
|
||||
let missingPeriod =
|
||||
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
let endOfPeriod = periodicity.periodEnd(missingPeriod)
|
||||
await ethProvider.advanceTimeTo(endOfPeriod + 1)
|
||||
await ethProvider.advanceTimeTo(endOfPeriod.u256 + 1)
|
||||
switchAccount(client)
|
||||
discard await marketplace.markProofAsMissing(slotId, missingPeriod).confirm(1)
|
||||
|
||||
@ -123,7 +125,8 @@ ethersuite "Marketplace contracts":
|
||||
let expiry = await marketplace.requestExpiry(request.id)
|
||||
await ethProvider.advanceTimeTo((expiry + 1).u256)
|
||||
switchAccount(client)
|
||||
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
|
||||
await ethProvider.advanceTime(periodicity.seconds)
|
||||
let missingPeriod =
|
||||
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
await ethProvider.advanceTime(periodicity.seconds.u256)
|
||||
expect Marketplace_SlotNotAcceptingProofs:
|
||||
discard await marketplace.markProofAsMissing(slotId, missingPeriod).confirm(1)
|
||||
|
||||
@ -25,7 +25,7 @@ ethersuite "On-Chain Market":
|
||||
var marketplace: Marketplace
|
||||
var token: Erc20Token
|
||||
var request: StorageRequest
|
||||
var slotIndex: UInt256
|
||||
var slotIndex: uint64
|
||||
var periodicity: Periodicity
|
||||
var host: Signer
|
||||
var otherHost: Signer
|
||||
@ -58,11 +58,12 @@ ethersuite "On-Chain Market":
|
||||
host = ethProvider.getSigner(accounts[1])
|
||||
otherHost = ethProvider.getSigner(accounts[3])
|
||||
|
||||
slotIndex = (request.ask.slots div 2).u256
|
||||
slotIndex = request.ask.slots div 2
|
||||
|
||||
proc advanceToNextPeriod() {.async.} =
|
||||
let currentPeriod = periodicity.periodOf(await ethProvider.currentTime())
|
||||
await ethProvider.advanceTimeTo(periodicity.periodEnd(currentPeriod) + 1)
|
||||
let currentPeriod =
|
||||
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
await ethProvider.advanceTimeTo((periodicity.periodEnd(currentPeriod) + 1).u256)
|
||||
|
||||
proc advanceToCancelledRequest(request: StorageRequest) {.async.} =
|
||||
let expiry = (await market.requestExpiresAt(request.id)) + 1
|
||||
@ -125,12 +126,13 @@ ethersuite "On-Chain Market":
|
||||
test "supports request subscriptions":
|
||||
var receivedIds: seq[RequestId]
|
||||
var receivedAsks: seq[StorageAsk]
|
||||
proc onRequest(id: RequestId, ask: StorageAsk, expiry: UInt256) =
|
||||
proc onRequest(id: RequestId, ask: StorageAsk, expiry: uint64) =
|
||||
receivedIds.add(id)
|
||||
receivedAsks.add(ask)
|
||||
|
||||
let subscription = await market.subscribeRequests(onRequest)
|
||||
await market.requestStorage(request)
|
||||
|
||||
check eventually receivedIds == @[request.id] and receivedAsks == @[request.ask]
|
||||
await subscription.unsubscribe()
|
||||
|
||||
@ -172,7 +174,8 @@ ethersuite "On-Chain Market":
|
||||
await market.reserveSlot(request.id, slotIndex)
|
||||
await market.fillSlot(request.id, slotIndex, proof, request.ask.collateralPerSlot)
|
||||
await waitUntilProofRequired(slotId)
|
||||
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
|
||||
let missingPeriod =
|
||||
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
await advanceToNextPeriod()
|
||||
await market.markProofAsMissing(slotId, missingPeriod)
|
||||
check (await marketplace.missingProofs(slotId)) == 1
|
||||
@ -183,15 +186,16 @@ ethersuite "On-Chain Market":
|
||||
await market.reserveSlot(request.id, slotIndex)
|
||||
await market.fillSlot(request.id, slotIndex, proof, request.ask.collateralPerSlot)
|
||||
await waitUntilProofRequired(slotId)
|
||||
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
|
||||
let missingPeriod =
|
||||
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
await advanceToNextPeriod()
|
||||
check (await market.canProofBeMarkedAsMissing(slotId, missingPeriod)) == true
|
||||
|
||||
test "supports slot filled subscriptions":
|
||||
await market.requestStorage(request)
|
||||
var receivedIds: seq[RequestId]
|
||||
var receivedSlotIndices: seq[UInt256]
|
||||
proc onSlotFilled(id: RequestId, slotIndex: UInt256) =
|
||||
var receivedSlotIndices: seq[uint64]
|
||||
proc onSlotFilled(id: RequestId, slotIndex: uint64) =
|
||||
receivedIds.add(id)
|
||||
receivedSlotIndices.add(slotIndex)
|
||||
|
||||
@ -206,8 +210,8 @@ ethersuite "On-Chain Market":
|
||||
test "subscribes only to a certain slot":
|
||||
var otherSlot = slotIndex - 1
|
||||
await market.requestStorage(request)
|
||||
var receivedSlotIndices: seq[UInt256]
|
||||
proc onSlotFilled(requestId: RequestId, slotIndex: UInt256) =
|
||||
var receivedSlotIndices: seq[uint64]
|
||||
proc onSlotFilled(requestId: RequestId, slotIndex: uint64) =
|
||||
receivedSlotIndices.add(slotIndex)
|
||||
|
||||
let subscription =
|
||||
@ -224,8 +228,8 @@ ethersuite "On-Chain Market":
|
||||
await market.reserveSlot(request.id, slotIndex)
|
||||
await market.fillSlot(request.id, slotIndex, proof, request.ask.collateralPerSlot)
|
||||
var receivedRequestIds: seq[RequestId] = @[]
|
||||
var receivedIdxs: seq[UInt256] = @[]
|
||||
proc onSlotFreed(requestId: RequestId, idx: UInt256) =
|
||||
var receivedIdxs: seq[uint64] = @[]
|
||||
proc onSlotFreed(requestId: RequestId, idx: uint64) =
|
||||
receivedRequestIds.add(requestId)
|
||||
receivedIdxs.add(idx)
|
||||
|
||||
@ -243,8 +247,8 @@ ethersuite "On-Chain Market":
|
||||
await market.requestStorage(request)
|
||||
|
||||
var receivedRequestIds: seq[RequestId] = @[]
|
||||
var receivedIdxs: seq[UInt256] = @[]
|
||||
proc onSlotReservationsFull(requestId: RequestId, idx: UInt256) =
|
||||
var receivedIdxs: seq[uint64] = @[]
|
||||
proc onSlotReservationsFull(requestId: RequestId, idx: uint64) =
|
||||
receivedRequestIds.add(requestId)
|
||||
receivedIdxs.add(idx)
|
||||
|
||||
@ -270,9 +274,9 @@ ethersuite "On-Chain Market":
|
||||
|
||||
let subscription = await market.subscribeFulfillment(request.id, onFulfillment)
|
||||
for slotIndex in 0 ..< request.ask.slots:
|
||||
await market.reserveSlot(request.id, slotIndex.u256)
|
||||
await market.reserveSlot(request.id, slotIndex.uint64)
|
||||
await market.fillSlot(
|
||||
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
|
||||
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
|
||||
)
|
||||
check eventually receivedIds == @[request.id]
|
||||
await subscription.unsubscribe()
|
||||
@ -291,14 +295,14 @@ ethersuite "On-Chain Market":
|
||||
let subscription = await market.subscribeFulfillment(request.id, onFulfillment)
|
||||
|
||||
for slotIndex in 0 ..< request.ask.slots:
|
||||
await market.reserveSlot(request.id, slotIndex.u256)
|
||||
await market.reserveSlot(request.id, slotIndex.uint64)
|
||||
await market.fillSlot(
|
||||
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
|
||||
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
|
||||
)
|
||||
for slotIndex in 0 ..< otherRequest.ask.slots:
|
||||
await market.reserveSlot(otherRequest.id, slotIndex.u256)
|
||||
await market.reserveSlot(otherRequest.id, slotIndex.uint64)
|
||||
await market.fillSlot(
|
||||
otherRequest.id, slotIndex.u256, proof, otherRequest.ask.collateralPerSlot
|
||||
otherRequest.id, slotIndex.uint64, proof, otherRequest.ask.collateralPerSlot
|
||||
)
|
||||
|
||||
check eventually receivedIds == @[request.id]
|
||||
@ -330,18 +334,19 @@ ethersuite "On-Chain Market":
|
||||
let subscription = await market.subscribeRequestFailed(request.id, onRequestFailed)
|
||||
|
||||
for slotIndex in 0 ..< request.ask.slots:
|
||||
await market.reserveSlot(request.id, slotIndex.u256)
|
||||
await market.reserveSlot(request.id, slotIndex.uint64)
|
||||
await market.fillSlot(
|
||||
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
|
||||
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
|
||||
)
|
||||
for slotIndex in 0 .. request.ask.maxSlotLoss:
|
||||
let slotId = request.slotId(slotIndex.u256)
|
||||
let slotId = request.slotId(slotIndex.uint64)
|
||||
while true:
|
||||
let slotState = await marketplace.slotState(slotId)
|
||||
if slotState == SlotState.Repair or slotState == SlotState.Failed:
|
||||
break
|
||||
await waitUntilProofRequired(slotId)
|
||||
let missingPeriod = periodicity.periodOf(await ethProvider.currentTime())
|
||||
let missingPeriod =
|
||||
periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
await advanceToNextPeriod()
|
||||
discard await marketplace.markProofAsMissing(slotId, missingPeriod).confirm(1)
|
||||
check eventually receivedIds == @[request.id]
|
||||
@ -395,9 +400,9 @@ ethersuite "On-Chain Market":
|
||||
test "can retrieve request state":
|
||||
await market.requestStorage(request)
|
||||
for slotIndex in 0 ..< request.ask.slots:
|
||||
await market.reserveSlot(request.id, slotIndex.u256)
|
||||
await market.reserveSlot(request.id, slotIndex.uint64)
|
||||
await market.fillSlot(
|
||||
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
|
||||
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
|
||||
)
|
||||
check (await market.requestState(request.id)) == some RequestState.Started
|
||||
|
||||
@ -460,13 +465,12 @@ ethersuite "On-Chain Market":
|
||||
|
||||
test "can query past SlotFilled events":
|
||||
await market.requestStorage(request)
|
||||
await market.reserveSlot(request.id, 0.u256)
|
||||
await market.reserveSlot(request.id, 1.u256)
|
||||
await market.reserveSlot(request.id, 2.u256)
|
||||
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 1.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 2.u256, proof, request.ask.collateralPerSlot)
|
||||
let slotId = request.slotId(slotIndex)
|
||||
await market.reserveSlot(request.id, 0.uint64)
|
||||
await market.reserveSlot(request.id, 1.uint64)
|
||||
await market.reserveSlot(request.id, 2.uint64)
|
||||
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 1.uint64, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 2.uint64, proof, request.ask.collateralPerSlot)
|
||||
|
||||
# `market.fill` executes an `approve` tx before the `fillSlot` tx, so that's
|
||||
# two PoA blocks per `fillSlot` call (6 blocks for 3 calls). We don't need
|
||||
@ -475,15 +479,15 @@ ethersuite "On-Chain Market":
|
||||
let events = await market.queryPastSlotFilledEvents(blocksAgo = 5)
|
||||
check events ==
|
||||
@[
|
||||
SlotFilled(requestId: request.id, slotIndex: 0.u256),
|
||||
SlotFilled(requestId: request.id, slotIndex: 1.u256),
|
||||
SlotFilled(requestId: request.id, slotIndex: 2.u256),
|
||||
SlotFilled(requestId: request.id, slotIndex: 0),
|
||||
SlotFilled(requestId: request.id, slotIndex: 1),
|
||||
SlotFilled(requestId: request.id, slotIndex: 2),
|
||||
]
|
||||
|
||||
test "can query past SlotFilled events since given timestamp":
|
||||
await market.requestStorage(request)
|
||||
await market.reserveSlot(request.id, 0.u256)
|
||||
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.reserveSlot(request.id, 0.uint64)
|
||||
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
|
||||
|
||||
# The SlotFilled event will be included in the same block as
|
||||
# the fillSlot transaction. If we want to ignore the SlotFilled event
|
||||
@ -494,10 +498,10 @@ ethersuite "On-Chain Market":
|
||||
|
||||
let (_, fromTime) = await ethProvider.blockNumberAndTimestamp(BlockTag.latest)
|
||||
|
||||
await market.reserveSlot(request.id, 1.u256)
|
||||
await market.reserveSlot(request.id, 2.u256)
|
||||
await market.fillSlot(request.id, 1.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 2.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.reserveSlot(request.id, 1.uint64)
|
||||
await market.reserveSlot(request.id, 2.uint64)
|
||||
await market.fillSlot(request.id, 1.uint64, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 2.uint64, proof, request.ask.collateralPerSlot)
|
||||
|
||||
let events = await market.queryPastSlotFilledEvents(
|
||||
fromTime = fromTime.truncate(SecondsSince1970)
|
||||
@ -505,19 +509,19 @@ ethersuite "On-Chain Market":
|
||||
|
||||
check events ==
|
||||
@[
|
||||
SlotFilled(requestId: request.id, slotIndex: 1.u256),
|
||||
SlotFilled(requestId: request.id, slotIndex: 2.u256),
|
||||
SlotFilled(requestId: request.id, slotIndex: 1),
|
||||
SlotFilled(requestId: request.id, slotIndex: 2),
|
||||
]
|
||||
|
||||
test "queryPastSlotFilledEvents returns empty sequence of events when " &
|
||||
"no SlotFilled events have occurred since given timestamp":
|
||||
await market.requestStorage(request)
|
||||
await market.reserveSlot(request.id, 0.u256)
|
||||
await market.reserveSlot(request.id, 1.u256)
|
||||
await market.reserveSlot(request.id, 2.u256)
|
||||
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 1.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 2.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.reserveSlot(request.id, 0.uint64)
|
||||
await market.reserveSlot(request.id, 1.uint64)
|
||||
await market.reserveSlot(request.id, 2.uint64)
|
||||
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 1.uint64, proof, request.ask.collateralPerSlot)
|
||||
await market.fillSlot(request.id, 2.uint64, proof, request.ask.collateralPerSlot)
|
||||
|
||||
await ethProvider.advanceTime(10.u256)
|
||||
|
||||
@ -542,21 +546,21 @@ ethersuite "On-Chain Market":
|
||||
|
||||
let address = await host.getAddress()
|
||||
switchAccount(host)
|
||||
await market.reserveSlot(request.id, 0.u256)
|
||||
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.reserveSlot(request.id, 0.uint64)
|
||||
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
|
||||
let filledAt = (await ethProvider.currentTime()) - 1.u256
|
||||
|
||||
for slotIndex in 1 ..< request.ask.slots:
|
||||
await market.reserveSlot(request.id, slotIndex.u256)
|
||||
await market.reserveSlot(request.id, slotIndex.uint64)
|
||||
await market.fillSlot(
|
||||
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
|
||||
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
|
||||
)
|
||||
|
||||
let requestEnd = await market.getRequestEnd(request.id)
|
||||
await ethProvider.advanceTimeTo(requestEnd.u256 + 1)
|
||||
|
||||
let startBalance = await token.balanceOf(address)
|
||||
await market.freeSlot(request.slotId(0.u256))
|
||||
await market.freeSlot(request.slotId(0.uint64))
|
||||
let endBalance = await token.balanceOf(address)
|
||||
|
||||
let expectedPayout = request.expectedPayout(filledAt, requestEnd.u256)
|
||||
@ -569,14 +573,14 @@ ethersuite "On-Chain Market":
|
||||
await market.requestStorage(request)
|
||||
|
||||
switchAccount(host)
|
||||
await market.reserveSlot(request.id, 0.u256)
|
||||
await market.fillSlot(request.id, 0.u256, proof, request.ask.collateralPerSlot)
|
||||
await market.reserveSlot(request.id, 0.uint64)
|
||||
await market.fillSlot(request.id, 0.uint64, proof, request.ask.collateralPerSlot)
|
||||
let filledAt = (await ethProvider.currentTime()) - 1.u256
|
||||
|
||||
for slotIndex in 1 ..< request.ask.slots:
|
||||
await market.reserveSlot(request.id, slotIndex.u256)
|
||||
await market.reserveSlot(request.id, slotIndex.uint64)
|
||||
await market.fillSlot(
|
||||
request.id, slotIndex.u256, proof, request.ask.collateralPerSlot
|
||||
request.id, slotIndex.uint64, proof, request.ask.collateralPerSlot
|
||||
)
|
||||
|
||||
let requestEnd = await market.getRequestEnd(request.id)
|
||||
@ -585,7 +589,7 @@ ethersuite "On-Chain Market":
|
||||
let startBalanceHost = await token.balanceOf(hostAddress)
|
||||
let startBalanceReward = await token.balanceOf(hostRewardRecipient)
|
||||
|
||||
await market.freeSlot(request.slotId(0.u256))
|
||||
await market.freeSlot(request.slotId(0.uint64))
|
||||
|
||||
let endBalanceHost = await token.balanceOf(hostAddress)
|
||||
let endBalanceReward = await token.balanceOf(hostRewardRecipient)
|
||||
|
||||
@ -49,8 +49,8 @@ proc example*(_: type StorageRequest): StorageRequest =
|
||||
client: Address.example,
|
||||
ask: StorageAsk(
|
||||
slots: 4,
|
||||
slotSize: (1 * 1024 * 1024 * 1024).u256, # 1 Gigabyte
|
||||
duration: (10 * 60 * 60).u256, # 10 hours
|
||||
slotSize: (1 * 1024 * 1024 * 1024).uint64, # 1 Gigabyte
|
||||
duration: (10 * 60 * 60).uint64, # 10 hours
|
||||
collateralPerByte: 1.u256,
|
||||
proofProbability: 4.u256, # require a proof roughly once every 4 periods
|
||||
pricePerBytePerSecond: 1.u256,
|
||||
@ -60,19 +60,19 @@ proc example*(_: type StorageRequest): StorageRequest =
|
||||
cid: Cid.init("zb2rhheVmk3bLks5MgzTqyznLu1zqGH5jrfTA1eAZXrjx7Vob").tryGet,
|
||||
merkleRoot: array[32, byte].example,
|
||||
),
|
||||
expiry: (60 * 60).u256, # 1 hour ,
|
||||
expiry: (60 * 60).uint64, # 1 hour ,
|
||||
nonce: Nonce.example,
|
||||
)
|
||||
|
||||
proc example*(_: type Slot): Slot =
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = rand(request.ask.slots.int).u256
|
||||
let slotIndex = rand(request.ask.slots.int).uint64
|
||||
Slot(request: request, slotIndex: slotIndex)
|
||||
|
||||
proc example*(_: type SlotQueueItem): SlotQueueItem =
|
||||
let request = StorageRequest.example
|
||||
let slot = Slot.example
|
||||
SlotQueueItem.init(request, slot.slotIndex.truncate(uint16))
|
||||
SlotQueueItem.init(request, slot.slotIndex.uint16)
|
||||
|
||||
proc example(_: type G1Point): G1Point =
|
||||
G1Point(x: UInt256.example, y: UInt256.example)
|
||||
|
||||
@ -117,11 +117,11 @@ proc space*(client: CodexClient): ?!RestRepoStore =
|
||||
proc requestStorageRaw*(
|
||||
client: CodexClient,
|
||||
cid: Cid,
|
||||
duration: UInt256,
|
||||
duration: uint64,
|
||||
pricePerBytePerSecond: UInt256,
|
||||
proofProbability: UInt256,
|
||||
collateralPerByte: UInt256,
|
||||
expiry: uint = 0,
|
||||
expiry: uint64 = 0,
|
||||
nodes: uint = 3,
|
||||
tolerance: uint = 1,
|
||||
): Response =
|
||||
@ -146,10 +146,10 @@ proc requestStorageRaw*(
|
||||
proc requestStorage*(
|
||||
client: CodexClient,
|
||||
cid: Cid,
|
||||
duration: UInt256,
|
||||
duration: uint64,
|
||||
pricePerBytePerSecond: UInt256,
|
||||
proofProbability: UInt256,
|
||||
expiry: uint,
|
||||
expiry: uint64,
|
||||
collateralPerByte: UInt256,
|
||||
nodes: uint = 3,
|
||||
tolerance: uint = 1,
|
||||
@ -187,7 +187,8 @@ proc getSlots*(client: CodexClient): ?!seq[Slot] =
|
||||
|
||||
proc postAvailability*(
|
||||
client: CodexClient,
|
||||
totalSize, duration, minPricePerBytePerSecond, totalCollateral: UInt256,
|
||||
totalSize, duration: uint64,
|
||||
minPricePerBytePerSecond, totalCollateral: UInt256,
|
||||
): ?!Availability =
|
||||
## Post sales availability endpoint
|
||||
##
|
||||
@ -207,8 +208,8 @@ proc postAvailability*(
|
||||
proc patchAvailabilityRaw*(
|
||||
client: CodexClient,
|
||||
availabilityId: AvailabilityId,
|
||||
totalSize, freeSize, duration, minPricePerBytePerSecond, totalCollateral: ?UInt256 =
|
||||
UInt256.none,
|
||||
totalSize, freeSize, duration: ?uint64 = uint64.none,
|
||||
minPricePerBytePerSecond, totalCollateral: ?UInt256 = UInt256.none,
|
||||
): Response =
|
||||
## Updates availability
|
||||
##
|
||||
@ -237,8 +238,8 @@ proc patchAvailabilityRaw*(
|
||||
proc patchAvailability*(
|
||||
client: CodexClient,
|
||||
availabilityId: AvailabilityId,
|
||||
totalSize, duration, minPricePerBytePerSecond, totalCollateral: ?UInt256 =
|
||||
UInt256.none,
|
||||
totalSize, duration: ?uint64 = uint64.none,
|
||||
minPricePerBytePerSecond, totalCollateral: ?UInt256 = UInt256.none,
|
||||
): void =
|
||||
let response = client.patchAvailabilityRaw(
|
||||
availabilityId,
|
||||
|
||||
@ -20,14 +20,14 @@ template marketplacesuite*(name: string, body: untyped) =
|
||||
var token {.inject, used.}: Erc20Token
|
||||
|
||||
proc getCurrentPeriod(): Future[Period] {.async.} =
|
||||
return periodicity.periodOf(await ethProvider.currentTime())
|
||||
return periodicity.periodOf((await ethProvider.currentTime()).truncate(uint64))
|
||||
|
||||
proc advanceToNextPeriod() {.async.} =
|
||||
let periodicity = Periodicity(seconds: period.u256)
|
||||
let currentTime = await ethProvider.currentTime()
|
||||
let periodicity = Periodicity(seconds: period)
|
||||
let currentTime = (await ethProvider.currentTime()).truncate(uint64)
|
||||
let currentPeriod = periodicity.periodOf(currentTime)
|
||||
let endOfPeriod = periodicity.periodEnd(currentPeriod)
|
||||
await ethProvider.advanceTimeTo(endOfPeriod + 1)
|
||||
await ethProvider.advanceTimeTo(endOfPeriod.u256 + 1)
|
||||
|
||||
template eventuallyP(condition: untyped, finalPeriod: Period): bool =
|
||||
proc eventuallyP(): Future[bool] {.async.} =
|
||||
@ -56,19 +56,19 @@ template marketplacesuite*(name: string, body: untyped) =
|
||||
return nodes.u256 * slotSize(blocks, nodes, tolerance)
|
||||
|
||||
proc createAvailabilities(
|
||||
datasetSize: UInt256,
|
||||
datasetSize: uint64,
|
||||
duration: uint64,
|
||||
collateralPerByte: UInt256,
|
||||
minPricePerBytePerSecond: UInt256,
|
||||
) =
|
||||
let totalCollateral = datasetSize * collateralPerByte
|
||||
let totalCollateral = datasetSize.u256 * collateralPerByte
|
||||
# post availability to each provider
|
||||
for i in 0 ..< providers().len:
|
||||
let provider = providers()[i].client
|
||||
|
||||
discard provider.postAvailability(
|
||||
totalSize = datasetSize,
|
||||
duration = duration.u256,
|
||||
duration = duration.uint64,
|
||||
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
totalCollateral = totalCollateral,
|
||||
)
|
||||
@ -76,7 +76,7 @@ template marketplacesuite*(name: string, body: untyped) =
|
||||
proc requestStorage(
|
||||
client: CodexClient,
|
||||
cid: Cid,
|
||||
proofProbability = 1,
|
||||
proofProbability = 1.u256,
|
||||
duration: uint64 = 12.periods,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
collateralPerByte = 1.u256,
|
||||
@ -86,9 +86,9 @@ template marketplacesuite*(name: string, body: untyped) =
|
||||
): Future[PurchaseId] {.async.} =
|
||||
let id = client.requestStorage(
|
||||
cid,
|
||||
expiry = expiry.uint,
|
||||
duration = duration.u256,
|
||||
proofProbability = proofProbability.u256,
|
||||
expiry = expiry,
|
||||
duration = duration,
|
||||
proofProbability = proofProbability,
|
||||
collateralPerByte = collateralPerByte,
|
||||
pricePerBytePerSecond = pricePerBytePerSecond,
|
||||
nodes = nodes.uint,
|
||||
@ -102,7 +102,7 @@ template marketplacesuite*(name: string, body: untyped) =
|
||||
let tokenAddress = await marketplace.token()
|
||||
token = Erc20Token.new(tokenAddress, ethProvider.getSigner())
|
||||
let config = await marketplace.configuration()
|
||||
period = config.proofs.period.truncate(uint64)
|
||||
periodicity = Periodicity(seconds: period.u256)
|
||||
period = config.proofs.period
|
||||
periodicity = Periodicity(seconds: period)
|
||||
|
||||
body
|
||||
|
||||
@ -34,28 +34,28 @@ marketplacesuite "Marketplace":
|
||||
await ethProvider.advanceTime(1.u256)
|
||||
|
||||
test "nodes negotiate contracts on the marketplace", marketplaceConfig:
|
||||
let size = 0xFFFFFF.u256
|
||||
let size = 0xFFFFFF.uint64
|
||||
let data = await RandomChunker.example(blocks = blocks)
|
||||
# host makes storage available
|
||||
let availability = host.postAvailability(
|
||||
totalSize = size,
|
||||
duration = 20 * 60.u256,
|
||||
duration = 20 * 60.uint64,
|
||||
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
totalCollateral = size * minPricePerBytePerSecond,
|
||||
totalCollateral = size.u256 * minPricePerBytePerSecond,
|
||||
).get
|
||||
|
||||
# client requests storage
|
||||
let cid = client.upload(data).get
|
||||
let id = client.requestStorage(
|
||||
let id = await client.requestStorage(
|
||||
cid,
|
||||
duration = 20 * 60.u256,
|
||||
duration = 20 * 60.uint64,
|
||||
pricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
proofProbability = 3.u256,
|
||||
expiry = 10 * 60,
|
||||
expiry = 10 * 60.uint64,
|
||||
collateralPerByte = collateralPerByte,
|
||||
nodes = ecNodes,
|
||||
tolerance = ecTolerance,
|
||||
).get
|
||||
)
|
||||
|
||||
check eventually(client.purchaseStateIs(id, "started"), timeout = 10 * 60 * 1000)
|
||||
let purchase = client.getPurchase(id).get
|
||||
@ -71,34 +71,34 @@ marketplacesuite "Marketplace":
|
||||
|
||||
test "node slots gets paid out and rest of tokens are returned to client",
|
||||
marketplaceConfig:
|
||||
let size = 0xFFFFFF.u256
|
||||
let size = 0xFFFFFF.uint64
|
||||
let data = await RandomChunker.example(blocks = blocks)
|
||||
let marketplace = Marketplace.new(Marketplace.address, ethProvider.getSigner())
|
||||
let tokenAddress = await marketplace.token()
|
||||
let token = Erc20Token.new(tokenAddress, ethProvider.getSigner())
|
||||
let duration = 20 * 60.u256
|
||||
let duration = 20 * 60.uint64
|
||||
|
||||
# host makes storage available
|
||||
let startBalanceHost = await token.balanceOf(hostAccount)
|
||||
discard host.postAvailability(
|
||||
totalSize = size,
|
||||
duration = 20 * 60.u256,
|
||||
duration = 20 * 60.uint64,
|
||||
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
totalCollateral = size * minPricePerBytePerSecond,
|
||||
totalCollateral = size.u256 * minPricePerBytePerSecond,
|
||||
).get
|
||||
|
||||
# client requests storage
|
||||
let cid = client.upload(data).get
|
||||
let id = client.requestStorage(
|
||||
let id = await client.requestStorage(
|
||||
cid,
|
||||
duration = duration,
|
||||
pricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
proofProbability = 3.u256,
|
||||
expiry = 10 * 60,
|
||||
expiry = 10 * 60.uint64,
|
||||
collateralPerByte = collateralPerByte,
|
||||
nodes = ecNodes,
|
||||
tolerance = ecTolerance,
|
||||
).get
|
||||
)
|
||||
|
||||
check eventually(client.purchaseStateIs(id, "started"), timeout = 10 * 60 * 1000)
|
||||
let purchase = client.getPurchase(id).get
|
||||
@ -109,13 +109,13 @@ marketplacesuite "Marketplace":
|
||||
# Proving mechanism uses blockchain clock to do proving/collect/cleanup round
|
||||
# hence we must use `advanceTime` over `sleepAsync` as Hardhat does mine new blocks
|
||||
# only with new transaction
|
||||
await ethProvider.advanceTime(duration)
|
||||
await ethProvider.advanceTime(duration.u256)
|
||||
|
||||
# Checking that the hosting node received reward for at least the time between <expiry;end>
|
||||
let slotSize = slotSize(blocks, ecNodes, ecTolerance)
|
||||
let pricePerSlotPerSecond = minPricePerBytePerSecond * slotSize
|
||||
check eventually (await token.balanceOf(hostAccount)) - startBalanceHost >=
|
||||
(duration - 5 * 60) * pricePerSlotPerSecond * ecNodes.u256
|
||||
(duration - 5 * 60).u256 * pricePerSlotPerSecond * ecNodes.u256
|
||||
|
||||
# Checking that client node receives some funds back that were not used for the host nodes
|
||||
check eventually(
|
||||
@ -157,19 +157,19 @@ marketplacesuite "Marketplace payouts":
|
||||
|
||||
# provider makes storage available
|
||||
let datasetSize = datasetSize(blocks, ecNodes, ecTolerance)
|
||||
let totalAvailabilitySize = datasetSize div 2
|
||||
let totalAvailabilitySize = (datasetSize div 2).truncate(uint64)
|
||||
discard providerApi.postAvailability(
|
||||
# make availability size small enough that we can't fill all the slots,
|
||||
# thus causing a cancellation
|
||||
totalSize = totalAvailabilitySize,
|
||||
duration = duration.u256,
|
||||
duration = duration.uint64,
|
||||
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
totalCollateral = collateralPerByte * totalAvailabilitySize,
|
||||
totalCollateral = collateralPerByte * totalAvailabilitySize.u256,
|
||||
)
|
||||
|
||||
let cid = clientApi.upload(data).get
|
||||
|
||||
var slotIdxFilled = none UInt256
|
||||
var slotIdxFilled = none uint64
|
||||
proc onSlotFilled(eventResult: ?!SlotFilled) =
|
||||
assert not eventResult.isErr
|
||||
slotIdxFilled = some (!eventResult).slotIndex
|
||||
|
||||
@ -43,7 +43,10 @@ marketplacesuite "Hosts submit regular proofs":
|
||||
let datasetSize =
|
||||
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
|
||||
createAvailabilities(
|
||||
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
|
||||
datasetSize.truncate(uint64),
|
||||
duration,
|
||||
collateralPerByte,
|
||||
minPricePerBytePerSecond,
|
||||
)
|
||||
|
||||
let cid = client0.upload(data).get
|
||||
@ -117,7 +120,10 @@ marketplacesuite "Simulate invalid proofs":
|
||||
let datasetSize =
|
||||
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
|
||||
createAvailabilities(
|
||||
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
|
||||
datasetSize.truncate(uint64),
|
||||
duration,
|
||||
collateralPerByte,
|
||||
minPricePerBytePerSecond,
|
||||
)
|
||||
|
||||
let cid = client0.upload(data).get
|
||||
@ -128,7 +134,7 @@ marketplacesuite "Simulate invalid proofs":
|
||||
duration = duration,
|
||||
nodes = ecNodes,
|
||||
tolerance = ecTolerance,
|
||||
proofProbability = 1,
|
||||
proofProbability = 1.u256,
|
||||
)
|
||||
let requestId = client0.requestId(purchaseId).get
|
||||
|
||||
@ -177,7 +183,10 @@ marketplacesuite "Simulate invalid proofs":
|
||||
let datasetSize =
|
||||
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
|
||||
createAvailabilities(
|
||||
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
|
||||
datasetSize.truncate(uint64),
|
||||
duration,
|
||||
collateralPerByte,
|
||||
minPricePerBytePerSecond,
|
||||
)
|
||||
|
||||
let cid = client0.upload(data).get
|
||||
@ -188,7 +197,7 @@ marketplacesuite "Simulate invalid proofs":
|
||||
duration = duration,
|
||||
nodes = ecNodes,
|
||||
tolerance = ecTolerance,
|
||||
proofProbability = 1,
|
||||
proofProbability = 1.u256,
|
||||
)
|
||||
let requestId = client0.requestId(purchaseId).get
|
||||
|
||||
|
||||
@ -11,18 +11,18 @@ twonodessuite "Purchasing":
|
||||
let cid = client1.upload(data).get
|
||||
let id1 = client1.requestStorage(
|
||||
cid,
|
||||
duration = 100.u256,
|
||||
duration = 100.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
expiry = 10,
|
||||
expiry = 10.uint64,
|
||||
collateralPerByte = 1.u256,
|
||||
).get
|
||||
let id2 = client1.requestStorage(
|
||||
cid,
|
||||
duration = 400.u256,
|
||||
duration = 400.uint64,
|
||||
pricePerBytePerSecond = 2.u256,
|
||||
proofProbability = 6.u256,
|
||||
expiry = 10,
|
||||
expiry = 10.uint64,
|
||||
collateralPerByte = 2.u256,
|
||||
).get
|
||||
check id1 != id2
|
||||
@ -37,10 +37,10 @@ twonodessuite "Purchasing":
|
||||
let cid = client1.upload(byteutils.toHex(data)).get
|
||||
let id = client1.requestStorage(
|
||||
cid,
|
||||
duration = 100.u256,
|
||||
duration = 100.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
expiry = 30,
|
||||
expiry = 30.uint64,
|
||||
collateralPerByte = 1.u256,
|
||||
nodes = 3,
|
||||
tolerance = 1,
|
||||
@ -49,10 +49,10 @@ twonodessuite "Purchasing":
|
||||
let request = client1.getPurchase(id).get.request.get
|
||||
|
||||
check request.content.cid.data.buffer.len > 0
|
||||
check request.ask.duration == 100.u256
|
||||
check request.ask.duration == 100.uint64
|
||||
check request.ask.pricePerBytePerSecond == 1.u256
|
||||
check request.ask.proofProbability == 3.u256
|
||||
check request.expiry == 30
|
||||
check request.expiry == 30.uint64
|
||||
check request.ask.collateralPerByte == 1.u256
|
||||
check request.ask.slots == 3'u64
|
||||
check request.ask.maxSlotLoss == 1'u64
|
||||
@ -78,10 +78,10 @@ twonodessuite "Purchasing":
|
||||
let cid = client1.upload(data).get
|
||||
let id = client1.requestStorage(
|
||||
cid,
|
||||
duration = 10 * 60.u256,
|
||||
duration = 10 * 60.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
expiry = 5 * 60,
|
||||
expiry = 5 * 60.uint64,
|
||||
collateralPerByte = 1.u256,
|
||||
nodes = 3.uint,
|
||||
tolerance = 1.uint,
|
||||
@ -93,10 +93,10 @@ twonodessuite "Purchasing":
|
||||
|
||||
check eventually(client1.purchaseStateIs(id, "submitted"), timeout = 3 * 60 * 1000)
|
||||
let request = client1.getPurchase(id).get.request.get
|
||||
check request.ask.duration == (10 * 60).u256
|
||||
check request.ask.duration == (10 * 60).uint64
|
||||
check request.ask.pricePerBytePerSecond == 1.u256
|
||||
check request.ask.proofProbability == 3.u256
|
||||
check request.expiry == (5 * 60).u256
|
||||
check request.expiry == (5 * 60).uint64
|
||||
check request.ask.collateralPerByte == 1.u256
|
||||
check request.ask.slots == 3'u64
|
||||
check request.ask.maxSlotLoss == 1'u64
|
||||
@ -107,7 +107,7 @@ twonodessuite "Purchasing":
|
||||
|
||||
let responseMissing = client1.requestStorageRaw(
|
||||
cid,
|
||||
duration = 1.u256,
|
||||
duration = 1.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
collateralPerByte = 1.u256,
|
||||
@ -117,11 +117,11 @@ twonodessuite "Purchasing":
|
||||
|
||||
let responseBefore = client1.requestStorageRaw(
|
||||
cid,
|
||||
duration = 10.u256,
|
||||
duration = 10.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
collateralPerByte = 1.u256,
|
||||
expiry = 10,
|
||||
expiry = 10.uint64,
|
||||
)
|
||||
check responseBefore.status == "400 Bad Request"
|
||||
check "Expiry needs value bigger then zero and smaller then the request's duration" in
|
||||
|
||||
@ -25,12 +25,12 @@ twonodessuite "REST API":
|
||||
|
||||
test "node shows used and available space", twoNodesConfig:
|
||||
discard client1.upload("some file contents").get
|
||||
let totalSize = 12.u256
|
||||
let totalSize = 12.uint64
|
||||
let minPricePerBytePerSecond = 1.u256
|
||||
let totalCollateral = totalSize * minPricePerBytePerSecond
|
||||
let totalCollateral = totalSize.u256 * minPricePerBytePerSecond
|
||||
discard client1.postAvailability(
|
||||
totalSize = totalSize,
|
||||
duration = 2.u256,
|
||||
duration = 2.uint64,
|
||||
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
totalCollateral = totalCollateral,
|
||||
).get
|
||||
@ -56,11 +56,11 @@ twonodessuite "REST API":
|
||||
let cid = client1.upload("some file contents").get
|
||||
let response = client1.requestStorageRaw(
|
||||
cid,
|
||||
duration = 10.u256,
|
||||
duration = 10.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
collateralPerByte = 1.u256,
|
||||
expiry = 9,
|
||||
expiry = 9.uint64,
|
||||
)
|
||||
|
||||
check:
|
||||
@ -74,11 +74,11 @@ twonodessuite "REST API":
|
||||
let cid = client1.upload(data).get
|
||||
let response = client1.requestStorageRaw(
|
||||
cid,
|
||||
duration = 10.u256,
|
||||
duration = 10.uint64,
|
||||
pricePerBytePerSecond = 1.u256,
|
||||
proofProbability = 3.u256,
|
||||
collateralPerByte = 1.u256,
|
||||
expiry = 9,
|
||||
expiry = 9.uint64,
|
||||
)
|
||||
|
||||
check:
|
||||
@ -87,10 +87,10 @@ twonodessuite "REST API":
|
||||
test "request storage fails if tolerance is zero", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = client1.upload(data).get
|
||||
let duration = 100.u256
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let nodes = 3
|
||||
let tolerance = 0
|
||||
@ -106,7 +106,7 @@ twonodessuite "REST API":
|
||||
test "request storage fails if duration exceeds limit", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = client1.upload(data).get
|
||||
let duration = (31 * 24 * 60 * 60).u256
|
||||
let duration = (31 * 24 * 60 * 60).uint64
|
||||
# 31 days TODO: this should not be hardcoded, but waits for https://github.com/codex-storage/nim-codex/issues/1056
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint
|
||||
@ -126,10 +126,10 @@ twonodessuite "REST API":
|
||||
test "request storage fails if nodes and tolerance aren't correct", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = client1.upload(data).get
|
||||
let duration = 100.u256
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)]
|
||||
|
||||
@ -149,10 +149,10 @@ twonodessuite "REST API":
|
||||
twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = 2)
|
||||
let cid = client1.upload(data).get
|
||||
let duration = 100.u256
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
let ecParams = @[(0, 1), (1, 2), (2, 3)]
|
||||
|
||||
@ -176,10 +176,10 @@ twonodessuite "REST API":
|
||||
fmt"({minBlocks=}, {nodes=}, {tolerance=})", twoNodesConfig:
|
||||
let data = await RandomChunker.example(blocks = minBlocks)
|
||||
let cid = client1.upload(data).get
|
||||
let duration = 100.u256
|
||||
let duration = 100.uint64
|
||||
let pricePerBytePerSecond = 1.u256
|
||||
let proofProbability = 3.u256
|
||||
let expiry = 30.uint
|
||||
let expiry = 30.uint64
|
||||
let collateralPerByte = 1.u256
|
||||
|
||||
var responseBefore = client1.requestStorageRaw(
|
||||
|
||||
@ -31,14 +31,14 @@ multinodesuite "Sales":
|
||||
|
||||
test "node handles new storage availability", salesConfig:
|
||||
let availability1 = host.postAvailability(
|
||||
totalSize = 1.u256,
|
||||
duration = 2.u256,
|
||||
totalSize = 1.uint64,
|
||||
duration = 2.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 4.u256,
|
||||
).get
|
||||
let availability2 = host.postAvailability(
|
||||
totalSize = 4.u256,
|
||||
duration = 5.u256,
|
||||
totalSize = 4.uint64,
|
||||
duration = 5.uint64,
|
||||
minPricePerBytePerSecond = 6.u256,
|
||||
totalCollateral = 7.u256,
|
||||
).get
|
||||
@ -46,8 +46,8 @@ multinodesuite "Sales":
|
||||
|
||||
test "node lists storage that is for sale", salesConfig:
|
||||
let availability = host.postAvailability(
|
||||
totalSize = 1.u256,
|
||||
duration = 2.u256,
|
||||
totalSize = 1.uint64,
|
||||
duration = 2.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 4.u256,
|
||||
).get
|
||||
@ -56,7 +56,7 @@ multinodesuite "Sales":
|
||||
test "updating non-existing availability", salesConfig:
|
||||
let nonExistingResponse = host.patchAvailabilityRaw(
|
||||
AvailabilityId.example,
|
||||
duration = 100.u256.some,
|
||||
duration = 100.uint64.some,
|
||||
minPricePerBytePerSecond = 2.u256.some,
|
||||
totalCollateral = 200.u256.some,
|
||||
)
|
||||
@ -64,60 +64,60 @@ multinodesuite "Sales":
|
||||
|
||||
test "updating availability", salesConfig:
|
||||
let availability = host.postAvailability(
|
||||
totalSize = 140000.u256,
|
||||
duration = 200.u256,
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
).get
|
||||
|
||||
host.patchAvailability(
|
||||
availability.id,
|
||||
duration = 100.u256.some,
|
||||
duration = 100.uint64.some,
|
||||
minPricePerBytePerSecond = 2.u256.some,
|
||||
totalCollateral = 200.u256.some,
|
||||
)
|
||||
|
||||
let updatedAvailability = (host.getAvailabilities().get).findItem(availability).get
|
||||
check updatedAvailability.duration == 100
|
||||
check updatedAvailability.duration == 100.uint64
|
||||
check updatedAvailability.minPricePerBytePerSecond == 2
|
||||
check updatedAvailability.totalCollateral == 200
|
||||
check updatedAvailability.totalSize == 140000
|
||||
check updatedAvailability.freeSize == 140000
|
||||
check updatedAvailability.totalSize == 140000.uint64
|
||||
check updatedAvailability.freeSize == 140000.uint64
|
||||
|
||||
test "updating availability - freeSize is not allowed to be changed", salesConfig:
|
||||
let availability = host.postAvailability(
|
||||
totalSize = 140000.u256,
|
||||
duration = 200.u256,
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
).get
|
||||
let freeSizeResponse =
|
||||
host.patchAvailabilityRaw(availability.id, freeSize = 110000.u256.some)
|
||||
host.patchAvailabilityRaw(availability.id, freeSize = 110000.uint64.some)
|
||||
check freeSizeResponse.status == "400 Bad Request"
|
||||
check "not allowed" in freeSizeResponse.body
|
||||
|
||||
test "updating availability - updating totalSize", salesConfig:
|
||||
let availability = host.postAvailability(
|
||||
totalSize = 140000.u256,
|
||||
duration = 200.u256,
|
||||
totalSize = 140000.uint64,
|
||||
duration = 200.uint64,
|
||||
minPricePerBytePerSecond = 3.u256,
|
||||
totalCollateral = 300.u256,
|
||||
).get
|
||||
host.patchAvailability(availability.id, totalSize = 100000.u256.some)
|
||||
host.patchAvailability(availability.id, totalSize = 100000.uint64.some)
|
||||
let updatedAvailability = (host.getAvailabilities().get).findItem(availability).get
|
||||
check updatedAvailability.totalSize == 100000
|
||||
check updatedAvailability.freeSize == 100000
|
||||
|
||||
test "updating availability - updating totalSize does not allow bellow utilized",
|
||||
salesConfig:
|
||||
let originalSize = 0xFFFFFF.u256
|
||||
let originalSize = 0xFFFFFF.uint64
|
||||
let data = await RandomChunker.example(blocks = 8)
|
||||
let minPricePerBytePerSecond = 3.u256
|
||||
let collateralPerByte = 1.u256
|
||||
let totalCollateral = originalSize * collateralPerByte
|
||||
let totalCollateral = originalSize.u256 * collateralPerByte
|
||||
let availability = host.postAvailability(
|
||||
totalSize = originalSize,
|
||||
duration = 20 * 60.u256,
|
||||
duration = 20 * 60.uint64,
|
||||
minPricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
totalCollateral = totalCollateral,
|
||||
).get
|
||||
@ -126,10 +126,10 @@ multinodesuite "Sales":
|
||||
let cid = client.upload(data).get
|
||||
let id = client.requestStorage(
|
||||
cid,
|
||||
duration = 20 * 60.u256,
|
||||
duration = 20 * 60.uint64,
|
||||
pricePerBytePerSecond = minPricePerBytePerSecond,
|
||||
proofProbability = 3.u256,
|
||||
expiry = 10 * 60,
|
||||
expiry = (10 * 60).uint64,
|
||||
collateralPerByte = collateralPerByte,
|
||||
nodes = 3,
|
||||
tolerance = 1,
|
||||
@ -140,9 +140,8 @@ multinodesuite "Sales":
|
||||
check updatedAvailability.totalSize != updatedAvailability.freeSize
|
||||
|
||||
let utilizedSize = updatedAvailability.totalSize - updatedAvailability.freeSize
|
||||
let totalSizeResponse = host.patchAvailabilityRaw(
|
||||
availability.id, totalSize = (utilizedSize - 1.u256).some
|
||||
)
|
||||
let totalSizeResponse =
|
||||
host.patchAvailabilityRaw(availability.id, totalSize = (utilizedSize - 1).some)
|
||||
check totalSizeResponse.status == "400 Bad Request"
|
||||
check "totalSize must be larger then current totalSize" in totalSizeResponse.body
|
||||
|
||||
|
||||
@ -37,7 +37,7 @@ marketplacesuite "Validation":
|
||||
const blocks = 8
|
||||
const ecNodes = 3
|
||||
const ecTolerance = 1
|
||||
const proofProbability = 1
|
||||
const proofProbability = 1.u256
|
||||
|
||||
const collateralPerByte = 1.u256
|
||||
const minPricePerBytePerSecond = 1.u256
|
||||
@ -100,7 +100,10 @@ marketplacesuite "Validation":
|
||||
let datasetSize =
|
||||
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
|
||||
createAvailabilities(
|
||||
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
|
||||
datasetSize.truncate(uint64),
|
||||
duration,
|
||||
collateralPerByte,
|
||||
minPricePerBytePerSecond,
|
||||
)
|
||||
|
||||
let cid = client0.upload(data).get
|
||||
@ -167,7 +170,10 @@ marketplacesuite "Validation":
|
||||
let datasetSize =
|
||||
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
|
||||
createAvailabilities(
|
||||
datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
|
||||
datasetSize.truncate(uint64),
|
||||
duration,
|
||||
collateralPerByte,
|
||||
minPricePerBytePerSecond,
|
||||
)
|
||||
|
||||
let cid = client0.upload(data).get
|
||||
|
||||
2
vendor/codex-contracts-eth
vendored
2
vendor/codex-contracts-eth
vendored
@ -1 +1 @@
|
||||
Subproject commit ff82c26b3669b52a09280c634141dace7f04659a
|
||||
Subproject commit 32a6c13def1c1505765e9e0dc465117fba98c161
|
||||
Loading…
x
Reference in New Issue
Block a user