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