formatting

This commit is contained in:
Mark Spanbroek 2025-04-15 16:07:22 +02:00
parent 0326399f7d
commit 307d85a700
No known key found for this signature in database
GPG Key ID: FBE3E9548D427C00
28 changed files with 186 additions and 192 deletions

View File

@ -109,9 +109,8 @@ proc bootstrapInteractions(s: CodexServer): Future[void] {.async.} =
quit QuitFailure quit QuitFailure
let marketplace = Marketplace.new(marketplaceAddress, signer) let marketplace = Marketplace.new(marketplaceAddress, signer)
without market =? await OnChainMarket.load( without market =?
marketplace, config.marketplaceRequestCacheSize await OnChainMarket.load(marketplace, config.marketplaceRequestCacheSize), error:
), error:
fatal "Cannot load market", error = error.msg fatal "Cannot load market", error = error.msg
quit QuitFailure quit QuitFailure

View File

@ -51,13 +51,10 @@ proc load*(
var requestCache = newLruCache[string, StorageRequest](int(requestCacheSize)) var requestCache = newLruCache[string, StorageRequest](int(requestCacheSize))
let market = OnChainMarket( let market =
contract: contract, OnChainMarket(contract: contract, signer: signer, requestCache: requestCache)
signer: signer,
requestCache: requestCache,
)
market.configuration = ? await market.loadConfig() market.configuration = ?await market.loadConfig()
return success market return success market
@ -114,7 +111,7 @@ method periodicity*(market: OnChainMarket): Periodicity =
let period = market.configuration.proofs.period let period = market.configuration.proofs.period
return Periodicity(seconds: period) return Periodicity(seconds: period)
method proofTimeout*(market: OnChainMarket): StorageDuration = method proofTimeout*(market: OnChainMarket): StorageDuration =
return market.configuration.proofs.timeout return market.configuration.proofs.timeout
method repairRewardPercentage*(market: OnChainMarket): uint8 = method repairRewardPercentage*(market: OnChainMarket): uint8 =

View File

@ -55,9 +55,7 @@ type
proc configuration*(marketplace: Marketplace): MarketplaceConfig {.contract, view.} proc configuration*(marketplace: Marketplace): MarketplaceConfig {.contract, view.}
proc token*(marketplace: Marketplace): Address {.contract, view.} proc token*(marketplace: Marketplace): Address {.contract, view.}
proc currentCollateral*( proc currentCollateral*(marketplace: Marketplace, id: SlotId): Tokens {.contract, view.}
marketplace: Marketplace, id: SlotId
): Tokens {.contract, view.}
proc requestStorage*( proc requestStorage*(
marketplace: Marketplace, request: StorageRequest marketplace: Marketplace, request: StorageRequest

View File

@ -1,9 +1,8 @@
import ../clock import ../clock
import ./requests import ./requests
type type Periodicity* = object
Periodicity* = object seconds*: StorageDuration
seconds*: StorageDuration
func periodOf*(periodicity: Periodicity, timestamp: StorageTimestamp): ProofPeriod = func periodOf*(periodicity: Periodicity, timestamp: StorageTimestamp): ProofPeriod =
ProofPeriod.init(timestamp.u40 div periodicity.seconds.u40) ProofPeriod.init(timestamp.u40 div periodicity.seconds.u40)

View File

@ -6,8 +6,10 @@ from ../clock import SecondsSince1970
type type
StorageTimestamp* = object StorageTimestamp* = object
value: StUint[40] value: StUint[40]
StorageDuration* = object StorageDuration* = object
value: StUint[40] value: StUint[40]
ProofPeriod* = object ProofPeriod* = object
value: StUint[40] value: StUint[40]
@ -43,7 +45,7 @@ func `'StorageDuration`*(value: static string): StorageDuration =
StorageDuration(value: parsed) StorageDuration(value: parsed)
func `'StorageTimestamp`*(value: static string): StorageTimestamp = func `'StorageTimestamp`*(value: static string): StorageTimestamp =
const parsed =parse(value, StUint[40]) const parsed = parse(value, StUint[40])
StorageTimestamp(value: parsed) StorageTimestamp(value: parsed)
func init*(_: type StorageDuration, value: StUint[40]): StorageDuration = func init*(_: type StorageDuration, value: StUint[40]): StorageDuration =
@ -158,11 +160,10 @@ func `%`*(value: StorageDuration | StorageTimestamp | ProofPeriod): JsonNode =
%value.value %value.value
func fromJson*(_: type StorageDuration, json: JsonNode): ?!StorageDuration = func fromJson*(_: type StorageDuration, json: JsonNode): ?!StorageDuration =
success StorageDuration(value: ? StUint[40].fromJson(json)) success StorageDuration(value: ?StUint[40].fromJson(json))
func fromJson*(_: type StorageTimestamp, json: JsonNode): ?!StorageTimestamp = func fromJson*(_: type StorageTimestamp, json: JsonNode): ?!StorageTimestamp =
success StorageTimestamp(value: ? StUint[40].fromJson(json)) success StorageTimestamp(value: ?StUint[40].fromJson(json))
func fromJson*(_: type ProofPeriod, json: JsonNode): ?!ProofPeriod = func fromJson*(_: type ProofPeriod, json: JsonNode): ?!ProofPeriod =
success ProofPeriod(value: ? StUint[40].fromJson(json)) success ProofPeriod(value: ?StUint[40].fromJson(json))

View File

@ -6,6 +6,7 @@ import ./timestamps
type type
TokensPerSecond* = object TokensPerSecond* = object
value: StUint[96] value: StUint[96]
Tokens* = object Tokens* = object
value: StUint[128] value: StUint[128]
@ -101,8 +102,7 @@ func `%`*(value: TokensPerSecond | Tokens): JsonNode =
%value.value %value.value
func fromJson*(_: type TokensPerSecond, json: JsonNode): ?!TokensPerSecond = func fromJson*(_: type TokensPerSecond, json: JsonNode): ?!TokensPerSecond =
success TokensPerSecond(value: ? StUint[96].fromJson(json)) success TokensPerSecond(value: ?StUint[96].fromJson(json))
func fromJson*(_: type Tokens, json: JsonNode): ?!Tokens = func fromJson*(_: type Tokens, json: JsonNode): ?!Tokens =
success Tokens(value: ? UInt128.fromJson(json)) success Tokens(value: ?UInt128.fromJson(json))

View File

@ -21,8 +21,9 @@ type
SlotStateMismatchError* = object of MarketError SlotStateMismatchError* = object of MarketError
SlotReservationNotAllowedError* = object of MarketError SlotReservationNotAllowedError* = object of MarketError
Subscription* = ref object of RootObj Subscription* = ref object of RootObj
OnRequest* = OnRequest* = proc(id: RequestId, ask: StorageAsk, expiry: StorageTimestamp) {.
proc(id: RequestId, ask: StorageAsk, expiry: StorageTimestamp) {.gcsafe, upraises: [].} gcsafe, upraises: []
.}
OnFulfillment* = proc(requestId: RequestId) {.gcsafe, upraises: [].} OnFulfillment* = proc(requestId: RequestId) {.gcsafe, upraises: [].}
OnSlotFilled* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].} OnSlotFilled* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
OnSlotFreed* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].} OnSlotFreed* = proc(requestId: RequestId, slotIndex: uint64) {.gcsafe, upraises: [].}
@ -65,19 +66,21 @@ method getSigner*(
): Future[Address] {.base, async: (raises: [CancelledError, MarketError]).} = ): Future[Address] {.base, async: (raises: [CancelledError, MarketError]).} =
raiseAssert("not implemented") raiseAssert("not implemented")
method zkeyHash*(market: Market): string {.base, gcsafe, raises:[].} = method zkeyHash*(market: Market): string {.base, gcsafe, raises: [].} =
raiseAssert("not implemented") raiseAssert("not implemented")
method periodicity*(market: Market): Periodicity {.base, gcsafe, raises:[].} = method periodicity*(market: Market): Periodicity {.base, gcsafe, raises: [].} =
raiseAssert("not implemented") raiseAssert("not implemented")
method proofTimeout*(market: Market): StorageDuration {.base, gcsafe, raises:[].} = method proofTimeout*(market: Market): StorageDuration {.base, gcsafe, raises: [].} =
raiseAssert("not implemented") raiseAssert("not implemented")
method repairRewardPercentage*(market: Market): uint8 {.base, gcsafe, raises:[].} = method repairRewardPercentage*(market: Market): uint8 {.base, gcsafe, raises: [].} =
raiseAssert("not implemented") raiseAssert("not implemented")
method requestDurationLimit*(market: Market): StorageDuration {.base, gcsafe, raises:[].} = method requestDurationLimit*(
market: Market
): StorageDuration {.base, gcsafe, raises: [].} =
raiseAssert("not implemented") raiseAssert("not implemented")
method proofDowntime*(market: Market): uint8 {.base, gcsafe, raises: [].} = method proofDowntime*(market: Market): uint8 {.base, gcsafe, raises: [].} =

View File

@ -341,9 +341,9 @@ proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: uint64) =
without slotQueueItem =? without slotQueueItem =?
SlotQueueItem.init(request, slotIndex.uint16, collateral, repairReward).catch, SlotQueueItem.init(request, slotIndex.uint16, collateral, repairReward).catch,
err: err:
warn "Too many slots, cannot add to queue", error = err.msgDetail warn "Too many slots, cannot add to queue", error = err.msgDetail
return return
if err =? queue.push(slotQueueItem).errorOption: if err =? queue.push(slotQueueItem).errorOption:
if err of SlotQueueItemExistsError: if err of SlotQueueItemExistsError:

View File

@ -30,7 +30,7 @@ type
expiry: StorageTimestamp, expiry: StorageTimestamp,
slot: uint64, slot: uint64,
blocksCb: BlocksCb, blocksCb: BlocksCb,
isRepairing: bool isRepairing: bool,
): 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: []

View File

@ -173,7 +173,9 @@ proc init*(
repairReward = 0'Tokens, repairReward = 0'Tokens,
seen = false, seen = false,
): SlotQueueItem = ): SlotQueueItem =
SlotQueueItem.init(requestId, slotIndex, ask, some expiry, collateral, repairReward, seen) SlotQueueItem.init(
requestId, slotIndex, ask, some expiry, collateral, repairReward, seen
)
proc init*( proc init*(
_: type SlotQueueItem, _: type SlotQueueItem,
@ -188,7 +190,7 @@ proc init*(
slotSize: request.ask.slotSize, slotSize: request.ask.slotSize,
duration: request.ask.duration, duration: request.ask.duration,
pricePerBytePerSecond: request.ask.pricePerBytePerSecond, pricePerBytePerSecond: request.ask.pricePerBytePerSecond,
collateral: collateral collateral: collateral,
) )
proc init( proc init(

View File

@ -51,10 +51,7 @@ method run*(
onClear(request, data.slotIndex) onClear(request, data.slotIndex)
if onCleanUp =? agent.onCleanUp: if onCleanUp =? agent.onCleanUp:
await onCleanUp( await onCleanUp(reprocessSlot = false, returnedCollateral = returnedCollateral)
reprocessSlot = false,
returnedCollateral = returnedCollateral,
)
warn "Sale cancelled due to timeout", warn "Sale cancelled due to timeout",
requestId = data.requestId, slotIndex = data.slotIndex requestId = data.requestId, slotIndex = data.slotIndex

View File

@ -81,7 +81,8 @@ method run*(
expiry = await market.requestExpiresAt(requestId) expiry = await market.requestExpiresAt(requestId)
trace "Starting download" trace "Starting download"
if err =? (await onStore(request, expiry, data.slotIndex, onBlocks, isRepairing)).errorOption: if err =?
(await onStore(request, expiry, data.slotIndex, onBlocks, isRepairing)).errorOption:
return some State(SaleErrored(error: err, reprocessSlot: false)) return some State(SaleErrored(error: err, reprocessSlot: false))
trace "Download complete" trace "Download complete"

View File

@ -72,11 +72,8 @@ method run*(
without availability =? without availability =?
await reservations.findAvailability( await reservations.findAvailability(
request.ask.slotSize, request.ask.slotSize, request.ask.duration, request.ask.pricePerBytePerSecond,
request.ask.duration, request.ask.collateralPerByte, requestEnd,
request.ask.pricePerBytePerSecond,
request.ask.collateralPerByte,
requestEnd
): ):
debug "No availability found for request, ignoring" debug "No availability found for request, ignoring"
@ -86,12 +83,8 @@ method run*(
without reservation =? without reservation =?
await reservations.createReservation( await reservations.createReservation(
availability.id, availability.id, request.ask.slotSize, request.id, data.slotIndex,
request.ask.slotSize, request.ask.collateralPerByte, requestEnd,
request.id,
data.slotIndex,
request.ask.collateralPerByte,
requestEnd
), error: ), error:
trace "Creation of reservation failed" trace "Creation of reservation failed"
# Race condition: # Race condition:

View File

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

View File

@ -501,7 +501,11 @@ method queryPastStorageRequestedEvents*(
): Future[seq[StorageRequested]] {.async.} = ): Future[seq[StorageRequested]] {.async.} =
return market.requested.map( return market.requested.map(
request => request =>
StorageRequested(requestId: request.id, ask: request.ask, expiry: market.requestExpiry[request.id]) StorageRequested(
requestId: request.id,
ask: request.ask,
expiry: market.requestExpiry[request.id],
)
) )
method queryPastStorageRequestedEvents*( method queryPastStorageRequestedEvents*(
@ -509,7 +513,11 @@ method queryPastStorageRequestedEvents*(
): Future[seq[StorageRequested]] {.async.} = ): Future[seq[StorageRequested]] {.async.} =
return market.requested.map( return market.requested.map(
request => request =>
StorageRequested(requestId: request.id, ask: request.ask, expiry: market.requestExpiry[request.id]) StorageRequested(
requestId: request.id,
ask: request.ask,
expiry: market.requestExpiry[request.id],
)
) )
method queryPastSlotFilledEvents*( method queryPastSlotFilledEvents*(

View File

@ -124,7 +124,11 @@ asyncchecksuite "Test Node - Host contracts":
fetchedBytes += blk.data.len.uint fetchedBytes += blk.data.len.uint
return success() return success()
(await onStore(request, StorageTimestamp.init(expiry), 1.uint64, onBlocks, isRepairing = false)).tryGet() (
await onStore(
request, StorageTimestamp.init(expiry), 1.uint64, onBlocks, isRepairing = false
)
).tryGet()
check fetchedBytes == 12 * DefaultBlockSize.uint check fetchedBytes == 12 * DefaultBlockSize.uint
let indexer = verifiable.protectedStrategy.init( let indexer = verifiable.protectedStrategy.init(

View File

@ -34,8 +34,7 @@ asyncchecksuite "sales state 'preparing'":
var reservations: MockReservations var reservations: MockReservations
setup: setup:
let collateral = let collateral = request.ask.collateralPerSlot * request.ask.slots
request.ask.collateralPerSlot * request.ask.slots
availability = Availability.init( availability = Availability.init(
totalSize = request.ask.slotSize + 100.uint64, totalSize = request.ask.slotSize + 100.uint64,
freeSize = request.ask.slotSize + 100.uint64, freeSize = request.ask.slotSize + 100.uint64,

View File

@ -69,22 +69,12 @@ asyncchecksuite "Reservations module":
test "generates unique ids for storage availability": test "generates unique ids for storage availability":
let availability1 = Availability.init( let availability1 = Availability.init(
1.uint64, 1.uint64, 2.uint64, 3'StorageDuration, 4'TokensPerSecond, 5'Tokens, true,
2.uint64, 0'StorageTimestamp,
3'StorageDuration,
4'TokensPerSecond,
5'Tokens,
true,
0'StorageTimestamp
) )
let availability2 = Availability.init( let availability2 = Availability.init(
1.uint64, 1.uint64, 2.uint64, 3'StorageDuration, 4'TokensPerSecond, 5'Tokens, true,
2.uint64, 0'StorageTimestamp,
3'StorageDuration,
4'TokensPerSecond,
5'Tokens,
true,
0'StorageTimestamp
) )
check availability1.id != availability2.id check availability1.id != availability2.id
@ -185,7 +175,7 @@ asyncchecksuite "Reservations module":
let two = reservations.createReservation( let two = reservations.createReservation(
availability.id, availability.totalSize, RequestId.example, uint64.example, availability.id, availability.totalSize, RequestId.example, uint64.example,
Tokens.example, validUntil Tokens.example, validUntil,
) )
let oneResult = await one let oneResult = await one

View File

@ -66,7 +66,7 @@ asyncchecksuite "Sales - start":
expiry: StorageTimestamp, expiry: StorageTimestamp,
slot: uint64, slot: uint64,
onBatch: BatchProc, onBatch: BatchProc,
isRepairing = false isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
return success() return success()
@ -187,7 +187,7 @@ asyncchecksuite "Sales":
expiry: StorageTimestamp, expiry: StorageTimestamp,
slot: uint64, slot: uint64,
onBatch: BatchProc, onBatch: BatchProc,
isRepairing = false isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
return success() return success()
@ -372,7 +372,11 @@ 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, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): 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.int)) await onBatch(blk.repeat(request.ask.slotSize.int))
@ -385,7 +389,11 @@ asyncchecksuite "Sales":
test "bytes are returned to availability once finished": test "bytes are returned to availability once finished":
var slotIndex = 0.uint64 var slotIndex = 0.uint64
sales.onStore = proc( sales.onStore = proc(
request: StorageRequest, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): 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
@ -455,14 +463,17 @@ asyncchecksuite "Sales":
check wasIgnored() check wasIgnored()
test "retrieves request when availability until terminates after the duration": test "retrieves request when availability until terminates after the duration":
let requestEnd = let requestEnd = StorageTimestamp.init(getTime().toUnix()) + request.ask.duration
StorageTimestamp.init(getTime().toUnix()) + request.ask.duration
let until = requestEnd + 1'StorageDuration let until = requestEnd + 1'StorageDuration
createAvailability(until = until) createAvailability(until = until)
var storingRequest: StorageRequest var storingRequest: StorageRequest
sales.onStore = proc( sales.onStore = proc(
request: StorageRequest, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
storingRequest = request storingRequest = request
return success() return success()
@ -475,7 +486,11 @@ asyncchecksuite "Sales":
var storingRequest: StorageRequest var storingRequest: StorageRequest
var storingSlot: uint64 var storingSlot: uint64
sales.onStore = proc( sales.onStore = proc(
request: StorageRequest, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
storingRequest = request storingRequest = request
storingSlot = slot storingSlot = slot
@ -488,7 +503,11 @@ asyncchecksuite "Sales":
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, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
return failure(error) return failure(error)
createAvailability() createAvailability()
@ -557,7 +576,11 @@ asyncchecksuite "Sales":
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, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
await sleepAsync(chronos.hours(1)) await sleepAsync(chronos.hours(1))
return success() return success()
@ -570,7 +593,11 @@ asyncchecksuite "Sales":
test "makes storage available again when request expires": test "makes storage available again when request expires":
let origSize = availability.freeSize let origSize = availability.freeSize
sales.onStore = proc( sales.onStore = proc(
request: StorageRequest, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
await sleepAsync(chronos.hours(1)) await sleepAsync(chronos.hours(1))
return success() return success()
@ -595,7 +622,11 @@ asyncchecksuite "Sales":
let origSize = availability.freeSize let origSize = availability.freeSize
sales.onStore = proc( sales.onStore = proc(
request: StorageRequest, expiry: StorageTimestamp, slot: uint64, onBatch: BatchProc, isRepairing = false request: StorageRequest,
expiry: StorageTimestamp,
slot: uint64,
onBatch: BatchProc,
isRepairing = false,
): Future[?!void] {.async.} = ): Future[?!void] {.async.} =
await sleepAsync(chronos.hours(1)) await sleepAsync(chronos.hours(1))
return success() return success()

View File

@ -176,10 +176,8 @@ suite "Slot queue":
check requestB.ask.pricePerSlot == 100000'Tokens * requestB.ask.slotSize check requestB.ask.pricePerSlot == 100000'Tokens * requestB.ask.slotSize
requestB.ask.collateralPerByte = 1'Tokens requestB.ask.collateralPerByte = 1'Tokens
let itemA = let itemA = SlotQueueItem.init(requestA, 0, requestA.ask.collateralPerSlot)
SlotQueueItem.init(requestA, 0, requestA.ask.collateralPerSlot) let itemB = SlotQueueItem.init(requestB, 0, requestB.ask.collateralPerSlot)
let itemB =
SlotQueueItem.init(requestB, 0, requestB.ask.collateralPerSlot)
check itemB < itemA # B higher priority than A check itemB < itemA # B higher priority than A
check itemA > itemB check itemA > itemB
@ -316,10 +314,7 @@ suite "Slot queue":
var checked = 0 var checked = 0
for slotIndex in 0'u16 ..< request.ask.slots.uint16: for slotIndex in 0'u16 ..< request.ask.slots.uint16:
check items.anyIt( check items.anyIt(
it == it == SlotQueueItem.init(request, slotIndex, request.ask.collateralPerSlot)
SlotQueueItem.init(
request, slotIndex, request.ask.collateralPerSlot
)
) )
inc checked inc checked
check checked == items.len check checked == items.len
@ -352,10 +347,7 @@ suite "Slot queue":
let uint64Slots = uint64(maxUInt16) let uint64Slots = uint64(maxUInt16)
request.ask.slots = uint64Slots request.ask.slots = uint64Slots
let items = SlotQueueItem.init( let items = SlotQueueItem.init(
request.id, request.id, request.ask, 0'StorageTimestamp, request.ask.collateralPerSlot
request.ask,
0'StorageTimestamp,
request.ask.collateralPerSlot,
) )
check items.len.uint16 == maxUInt16 check items.len.uint16 == maxUInt16
@ -366,10 +358,7 @@ suite "Slot queue":
request.ask.slots = uint64Slots request.ask.slots = uint64Slots
expect SlotsOutOfRangeError: expect SlotsOutOfRangeError:
discard SlotQueueItem.init( discard SlotQueueItem.init(
request.id, request.id, request.ask, 0'StorageTimestamp, request.ask.collateralPerSlot
request.ask,
0'StorageTimestamp,
request.ask.collateralPerSlot,
) )
test "cannot push duplicate items": test "cannot push duplicate items":
@ -411,10 +400,8 @@ suite "Slot queue":
let request0 = StorageRequest.example let request0 = StorageRequest.example
var request1 = StorageRequest.example var request1 = StorageRequest.example
request1.ask.collateralPerByte += 1'Tokens request1.ask.collateralPerByte += 1'Tokens
let items0 = let items0 = SlotQueueItem.init(request0, request0.ask.collateralPerSlot)
SlotQueueItem.init(request0, request0.ask.collateralPerSlot) let items1 = SlotQueueItem.init(request1, request1.ask.collateralPerSlot)
let items1 =
SlotQueueItem.init(request1, request1.ask.collateralPerSlot)
check queue.push(items0).isOk check queue.push(items0).isOk
check queue.push(items1).isOk check queue.push(items1).isOk
let last = items1[items1.high] let last = items1[items1.high]
@ -427,10 +414,8 @@ suite "Slot queue":
let request0 = StorageRequest.example let request0 = StorageRequest.example
var request1 = StorageRequest.example var request1 = StorageRequest.example
request1.ask.collateralPerByte += 1'Tokens request1.ask.collateralPerByte += 1'Tokens
let items0 = let items0 = SlotQueueItem.init(request0, request0.ask.collateralPerSlot)
SlotQueueItem.init(request0, request0.ask.collateralPerSlot) let items1 = SlotQueueItem.init(request1, request1.ask.collateralPerSlot)
let items1 =
SlotQueueItem.init(request1, request1.ask.collateralPerSlot)
check queue.push(items0).isOk check queue.push(items0).isOk
check queue.push(items1).isOk check queue.push(items1).isOk
queue.delete(request1.id) queue.delete(request1.id)
@ -449,55 +434,45 @@ suite "Slot queue":
request3.ask.collateralPerByte = request2.ask.collateralPerByte + 1 request3.ask.collateralPerByte = request2.ask.collateralPerByte + 1
request4.ask.collateralPerByte = request3.ask.collateralPerByte + 1 request4.ask.collateralPerByte = request3.ask.collateralPerByte + 1
request5.ask.collateralPerByte = request4.ask.collateralPerByte + 1 request5.ask.collateralPerByte = request4.ask.collateralPerByte + 1
let item0 = let item0 = SlotQueueItem.init(request0, 0, request0.ask.collateralPerSlot)
SlotQueueItem.init(request0, 0, request0.ask.collateralPerSlot) let item1 = SlotQueueItem.init(request1, 0, request1.ask.collateralPerSlot)
let item1 = let item2 = SlotQueueItem.init(request2, 0, request2.ask.collateralPerSlot)
SlotQueueItem.init(request1, 0, request1.ask.collateralPerSlot) let item3 = SlotQueueItem.init(request3, 0, request3.ask.collateralPerSlot)
let item2 = let item4 = SlotQueueItem.init(request4, 0, request4.ask.collateralPerSlot)
SlotQueueItem.init(request2, 0, request2.ask.collateralPerSlot) let item5 = SlotQueueItem.init(request5, 0, request5.ask.collateralPerSlot)
let item3 =
SlotQueueItem.init(request3, 0, request3.ask.collateralPerSlot)
let item4 =
SlotQueueItem.init(request4, 0, request4.ask.collateralPerSlot)
let item5 =
SlotQueueItem.init(request5, 0, request5.ask.collateralPerSlot)
check queue.contains(item5) == false check queue.contains(item5) == false
check queue.push(@[item0, item1, item2, item3, item4, item5]).isOk check queue.push(@[item0, item1, item2, item3, item4, item5]).isOk
check queue.contains(item5) check queue.contains(item5)
test "sorts items by profitability descending (higher pricePerBytePerSecond == higher priority == goes first in the list)": test "sorts items by profitability descending (higher pricePerBytePerSecond == higher priority == goes first in the list)":
var request = StorageRequest.example var request = StorageRequest.example
let item0 = let item0 = SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
request.ask.pricePerBytePerSecond += 1'TokensPerSecond request.ask.pricePerBytePerSecond += 1'TokensPerSecond
let item1 = let item1 = SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
check item1 < item0 check item1 < item0
test "sorts items by collateral ascending (higher required collateral = lower priority == comes later in the list)": test "sorts items by collateral ascending (higher required collateral = lower priority == comes later in the list)":
var request = StorageRequest.example var request = StorageRequest.example
let item0 = let item0 = SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 0, request.ask.collateralPerSlot) let item1 = SlotQueueItem.init(request, 1, request.ask.collateralPerSlot +
let item1 = SlotQueueItem.init( 1'Tokens)
request, 1, request.ask.collateralPerSlot + 1'Tokens
)
check item1 > item0 check item1 > item0
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 = let item0 = SlotQueueItem.init(
SlotQueueItem.init(request.id, 0, request.ask, 3'StorageTimestamp, request.ask.collateralPerSlot) request.id, 0, request.ask, 3'StorageTimestamp, request.ask.collateralPerSlot
let item1 = )
SlotQueueItem.init(request.id, 1, request.ask, 7'StorageTimestamp, request.ask.collateralPerSlot) let item1 = SlotQueueItem.init(
request.id, 1, request.ask, 7'StorageTimestamp, request.ask.collateralPerSlot
)
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 = let item0 = SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
request.ask.slotSize += 1 request.ask.slotSize += 1
let item1 = let item1 = SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
check item1 < item0 check item1 < item0
test "should call callback once an item is added": test "should call callback once an item is added":
@ -518,17 +493,13 @@ suite "Slot queue":
# sleeping after push allows the slotqueue loop to iterate, # sleeping after push allows the slotqueue loop to iterate,
# calling the callback for each pushed/updated item # calling the callback for each pushed/updated item
var request = StorageRequest.example var request = StorageRequest.example
let item0 = let item0 = SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
request.ask.pricePerBytePerSecond += 1'TokensPerSecond request.ask.pricePerBytePerSecond += 1'TokensPerSecond
let item1 = let item1 = SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
request.ask.pricePerBytePerSecond += 1'TokensPerSecond request.ask.pricePerBytePerSecond += 1'TokensPerSecond
let item2 = let item2 = SlotQueueItem.init(request, 2, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 2, request.ask.collateralPerSlot)
request.ask.pricePerBytePerSecond += 1'TokensPerSecond request.ask.pricePerBytePerSecond += 1'TokensPerSecond
let item3 = let item3 = SlotQueueItem.init(request, 3, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 3, request.ask.collateralPerSlot)
check queue.push(item0).isOk check queue.push(item0).isOk
await sleepAsync(1.millis) await sleepAsync(1.millis)
@ -553,17 +524,13 @@ suite "Slot queue":
# sleeping after push allows the slotqueue loop to iterate, # sleeping after push allows the slotqueue loop to iterate,
# calling the callback for each pushed/updated item # calling the callback for each pushed/updated item
var request = StorageRequest.example var request = StorageRequest.example
let item0 = let item0 = SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 0, request.ask.collateralPerSlot)
request.ask.pricePerBytePerSecond += 1'TokensPerSecond request.ask.pricePerBytePerSecond += 1'TokensPerSecond
let item1 = let item1 = SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 1, request.ask.collateralPerSlot)
request.ask.pricePerBytePerSecond += 1'TokensPerSecond request.ask.pricePerBytePerSecond += 1'TokensPerSecond
let item2 = let item2 = SlotQueueItem.init(request, 2, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 2, request.ask.collateralPerSlot)
request.ask.pricePerBytePerSecond += 1'TokensPerSecond request.ask.pricePerBytePerSecond += 1'TokensPerSecond
let item3 = let item3 = SlotQueueItem.init(request, 3, request.ask.collateralPerSlot)
SlotQueueItem.init(request, 3, request.ask.collateralPerSlot)
check queue.push(item0).isOk check queue.push(item0).isOk
check queue.push(item1).isOk check queue.push(item1).isOk

View File

@ -30,20 +30,22 @@ ethersuite "On-Chain Market":
var host: Signer var host: Signer
var otherHost: Signer var otherHost: Signer
proc expectedPayout(request: StorageRequest, start, finish: StorageTimestamp): Tokens = proc expectedPayout(
request: StorageRequest, start, finish: StorageTimestamp
): Tokens =
return request.ask.pricePerSlotPerSecond * start.until(finish) return request.ask.pricePerSlotPerSecond * start.until(finish)
proc switchAccount(account: Signer) {.async.} = proc switchAccount(account: Signer) {.async.} =
marketplace = marketplace.connect(account) marketplace = marketplace.connect(account)
token = token.connect(account) token = token.connect(account)
market = ! await OnChainMarket.load(marketplace) market = !await OnChainMarket.load(marketplace)
setup: setup:
let address = Marketplace.address(dummyVerifier = true) let address = Marketplace.address(dummyVerifier = true)
marketplace = Marketplace.new(address, ethProvider.getSigner()) marketplace = Marketplace.new(address, ethProvider.getSigner())
let config = await marketplace.configuration() let config = await marketplace.configuration()
market = ! await OnChainMarket.load(marketplace) market = !await OnChainMarket.load(marketplace)
let tokenAddress = await marketplace.token() let tokenAddress = await marketplace.token()
token = Erc20Token.new(tokenAddress, ethProvider.getSigner()) token = Erc20Token.new(tokenAddress, ethProvider.getSigner())
@ -535,7 +537,8 @@ ethersuite "On-Chain Market":
let endBalance = await token.balanceOf(address) let endBalance = await token.balanceOf(address)
let expectedPayout = request.expectedPayout(filledAt, requestEnd) let expectedPayout = request.expectedPayout(filledAt, requestEnd)
check (endBalance - startBalance) == (expectedPayout + request.ask.collateralPerSlot).u256 check (endBalance - startBalance) ==
(expectedPayout + request.ask.collateralPerSlot).u256
test "the request is added to cache after the first access": test "the request is added to cache after the first access":
await market.requestStorage(request) await market.requestStorage(request)

View File

@ -255,8 +255,14 @@ proc requestStorageRaw*(
tolerance: uint = 1, tolerance: uint = 1,
): Future[HttpClientResponseRef] {.async: (raises: [CancelledError, HttpError]).} = ): Future[HttpClientResponseRef] {.async: (raises: [CancelledError, HttpError]).} =
return await client.requestStorageRaw( return await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, cid,
some expiry, nodes, tolerance duration,
pricePerBytePerSecond,
proofProbability,
collateralPerByte,
some expiry,
nodes,
tolerance,
) )
proc requestStorage*( proc requestStorage*(
@ -295,8 +301,14 @@ proc requestStorage*(
tolerance: uint = 1, tolerance: uint = 1,
): Future[?!PurchaseId] {.async: (raises: [CancelledError, HttpError]).} = ): Future[?!PurchaseId] {.async: (raises: [CancelledError, HttpError]).} =
return await client.requestStorage( return await client.requestStorage(
cid, duration, pricePerBytePerSecond, proofProbability, some expiry, cid,
collateralPerByte, nodes, tolerance duration,
pricePerBytePerSecond,
proofProbability,
some expiry,
collateralPerByte,
nodes,
tolerance,
) )
proc getPurchase*( proc getPurchase*(

View File

@ -213,7 +213,8 @@ marketplacesuite "Marketplace payouts":
check eventually ( check eventually (
let endBalanceProvider = (await token.balanceOf(provider.ethAccount)) let endBalanceProvider = (await token.balanceOf(provider.ethAccount))
endBalanceProvider > startBalanceProvider and endBalanceProvider > startBalanceProvider and
endBalanceProvider < startBalanceProvider + expiry.u256 * pricePerSlotPerSecond.u256 endBalanceProvider <
startBalanceProvider + expiry.u256 * pricePerSlotPerSecond.u256
) )
check eventually( check eventually(
( (

View File

@ -43,10 +43,7 @@ marketplacesuite "Hosts submit regular proofs":
let datasetSize = let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance) datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
await createAvailabilities( await createAvailabilities(
datasetSize, datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
duration,
collateralPerByte,
minPricePerBytePerSecond,
) )
let cid = (await client0.upload(data)).get let cid = (await client0.upload(data)).get
@ -65,7 +62,8 @@ marketplacesuite "Hosts submit regular proofs":
let slotSize = slotSize(blocks, ecNodes, ecTolerance) let slotSize = slotSize(blocks, ecNodes, ecTolerance)
check eventually( check eventually(
await client0.purchaseStateIs(purchaseId, "started"), timeout = expiry.u64.int * 1000 await client0.purchaseStateIs(purchaseId, "started"),
timeout = expiry.u64.int * 1000,
) )
var proofWasSubmitted = false var proofWasSubmitted = false
@ -120,10 +118,7 @@ marketplacesuite "Simulate invalid proofs":
let datasetSize = let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance) datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
await createAvailabilities( await createAvailabilities(
datasetSize, datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
duration,
collateralPerByte,
minPricePerBytePerSecond,
) )
let cid = (await client0.upload(data)).get let cid = (await client0.upload(data)).get
@ -141,7 +136,8 @@ marketplacesuite "Simulate invalid proofs":
let requestId = (await client0.requestId(purchaseId)).get let requestId = (await client0.requestId(purchaseId)).get
check eventually( check eventually(
await client0.purchaseStateIs(purchaseId, "started"), timeout = expiry.u64.int * 1000 await client0.purchaseStateIs(purchaseId, "started"),
timeout = expiry.u64.int * 1000,
) )
var slotWasFreed = false var slotWasFreed = false
@ -185,10 +181,7 @@ marketplacesuite "Simulate invalid proofs":
let datasetSize = let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance) datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
await createAvailabilities( await createAvailabilities(
datasetSize, datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
duration,
collateralPerByte,
minPricePerBytePerSecond,
) )
let cid = (await client0.upload(data)).get let cid = (await client0.upload(data)).get

View File

@ -1,4 +1,3 @@
import std/importutils import std/importutils
import std/net import std/net
import std/sequtils import std/sequtils

View File

@ -69,7 +69,7 @@ multinodesuite "Rest API validation":
expiry = 30'StorageDuration, expiry = 30'StorageDuration,
collateralPerByte = 1'Tokens, collateralPerByte = 1'Tokens,
nodes = nodes.uint, nodes = nodes.uint,
tolerance =tolerance.uint, tolerance = tolerance.uint,
) )
) )
@ -241,7 +241,8 @@ multinodesuite "Rest API validation":
let response = await client.requestStorageRaw( let response = await client.requestStorageRaw(
cid, cid,
duration = StorageDuration.init(31'u32 * 24 * 60 * 60), # 31 days TODO: this should not be hardcoded, but waits for https://github.com/codex-storage/nim-codex/issues/1056 duration = StorageDuration.init(31'u32 * 24 * 60 * 60),
# 31 days TODO: this should not be hardcoded, but waits for https://github.com/codex-storage/nim-codex/issues/1056
pricePerBytePerSecond = 1'TokensPerSecond, pricePerBytePerSecond = 1'TokensPerSecond,
proofProbability = 3.u256, proofProbability = 3.u256,
expiry = 30'StorageDuration, expiry = 30'StorageDuration,
@ -306,8 +307,7 @@ multinodesuite "Rest API validation":
) )
check response.status == 422 check response.status == 422
check (await response.body) == check (await response.body) == "Price per byte per second must be greater than zero"
"Price per byte per second must be greater than zero"
test "request storage fails if collareral per byte is zero", config: test "request storage fails if collareral per byte is zero", config:
let data = await RandomChunker.example(blocks = 2) let data = await RandomChunker.example(blocks = 2)

View File

@ -86,7 +86,8 @@ multinodesuite "Sales":
let updatedAvailability = let updatedAvailability =
((await host.getAvailabilities()).get).findItem(availability).get ((await host.getAvailabilities()).get).findItem(availability).get
check updatedAvailability.duration == 100'StorageDuration check updatedAvailability.duration == 100'StorageDuration
check updatedAvailability.minPricePerBytePerSecond == 2'TokensPerSecond check updatedAvailability.minPricePerBytePerSecond ==
2'TokensPerSecond
check updatedAvailability.totalCollateral == 200'Tokens check updatedAvailability.totalCollateral == 200'Tokens
check updatedAvailability.totalSize == 140000.uint64 check updatedAvailability.totalSize == 140000.uint64
check updatedAvailability.freeSize == 140000.uint64 check updatedAvailability.freeSize == 140000.uint64

View File

@ -100,10 +100,7 @@ marketplacesuite "Validation":
let datasetSize = let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance) datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
await createAvailabilities( await createAvailabilities(
datasetSize, datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
duration,
collateralPerByte,
minPricePerBytePerSecond,
) )
let cid = (await client0.upload(data)).get let cid = (await client0.upload(data)).get
@ -170,10 +167,7 @@ marketplacesuite "Validation":
let datasetSize = let datasetSize =
datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance) datasetSize(blocks = blocks, nodes = ecNodes, tolerance = ecTolerance)
await createAvailabilities( await createAvailabilities(
datasetSize, datasetSize, duration, collateralPerByte, minPricePerBytePerSecond
duration,
collateralPerByte,
minPricePerBytePerSecond,
) )
let cid = (await client0.upload(data)).get let cid = (await client0.upload(data)).get