Skip to content

Commit

Permalink
API tweaks for OpenAPI, errors and endpoints (#886)
Browse files Browse the repository at this point in the history
* All sort of tweaks

* docs: availability's minPrice doc

* Revert changes to the two node test example

* Change default EC params in REST API

Change default EC params in REST API to 3 nodes and 1 tolerance.

Adjust integration tests to honour these settings.

---------

Co-authored-by: Eric <[email protected]>
  • Loading branch information
AuHau and emizzle authored Sep 24, 2024
1 parent 098c4bb commit 4b9336e
Show file tree
Hide file tree
Showing 10 changed files with 133 additions and 53 deletions.
8 changes: 4 additions & 4 deletions codex/contracts/requests.nim
Original file line number Diff line number Diff line change
Expand Up @@ -163,12 +163,12 @@ func id*(request: StorageRequest): RequestId =
let encoding = AbiEncoder.encode((request, ))
RequestId(keccak256.digest(encoding).data)

func slotId*(requestId: RequestId, slot: UInt256): SlotId =
let encoding = AbiEncoder.encode((requestId, slot))
func slotId*(requestId: RequestId, slotIndex: UInt256): SlotId =
let encoding = AbiEncoder.encode((requestId, slotIndex))
SlotId(keccak256.digest(encoding).data)

func slotId*(request: StorageRequest, slot: UInt256): SlotId =
slotId(request.id, slot)
func slotId*(request: StorageRequest, slotIndex: UInt256): SlotId =
slotId(request.id, slotIndex)

func id*(slot: Slot): SlotId =
slotId(slot.request, slot.slotIndex)
Expand Down
34 changes: 20 additions & 14 deletions codex/rest/api.nim
Original file line number Diff line number Diff line change
Expand Up @@ -232,7 +232,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
## Returns active slots for the host
try:
without contracts =? node.contracts.host:
return RestApiResponse.error(Http503, "Sales unavailable")
return RestApiResponse.error(Http503, "Persistence is not enabled")

let json = %(await contracts.sales.mySlots())
return RestApiResponse.response($json, contentType="application/json")
Expand All @@ -247,7 +247,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
## slot is not active for the host.

without contracts =? node.contracts.host:
return RestApiResponse.error(Http503, "Sales unavailable")
return RestApiResponse.error(Http503, "Persistence is not enabled")

without slotId =? slotId.tryGet.catch, error:
return RestApiResponse.error(Http400, error.msg)
Expand All @@ -258,7 +258,9 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
let restAgent = RestSalesAgent(
state: agent.state() |? "none",
slotIndex: agent.data.slotIndex,
requestId: agent.data.requestId
requestId: agent.data.requestId,
request: agent.data.request,
reservation: agent.data.reservation,
)

return RestApiResponse.response(restAgent.toJson, contentType="application/json")
Expand All @@ -270,7 +272,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =

try:
without contracts =? node.contracts.host:
return RestApiResponse.error(Http503, "Sales unavailable")
return RestApiResponse.error(Http503, "Persistence is not enabled")

without avails =? (await contracts.sales.context.reservations.all(Availability)), err:
return RestApiResponse.error(Http500, err.msg)
Expand All @@ -289,7 +291,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
##
## totalSize - size of available storage in bytes
## duration - maximum time the storage should be sold for (in seconds)
## minPrice - minimum price to be paid (in amount of tokens)
## minPrice - minimal price paid (in amount of tokens) for the whole hosted request's slot for the request's duration
## maxCollateral - maximum collateral user is willing to pay per filled Slot (in amount of tokens)

var headers = newSeq[(string,string)]()
Expand All @@ -301,7 +303,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =

try:
without contracts =? node.contracts.host:
return RestApiResponse.error(Http503, "Sales unavailable", headers = headers)
return RestApiResponse.error(Http503, "Persistence is not enabled", headers = headers)

let body = await request.getBody()

Expand Down Expand Up @@ -359,7 +361,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =

try:
without contracts =? node.contracts.host:
return RestApiResponse.error(Http503, "Sales unavailable")
return RestApiResponse.error(Http503, "Persistence is not enabled")

without id =? id.tryGet.catch, error:
return RestApiResponse.error(Http400, error.msg)
Expand Down Expand Up @@ -415,14 +417,15 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =

try:
without contracts =? node.contracts.host:
return RestApiResponse.error(Http503, "Sales unavailable")
return RestApiResponse.error(Http503, "Persistence is not enabled")

without id =? id.tryGet.catch, error:
return RestApiResponse.error(Http400, error.msg)
without keyId =? id.key.tryGet.catch, error:
return RestApiResponse.error(Http400, error.msg)

let reservations = contracts.sales.context.reservations
let market = contracts.sales.context.market

if error =? (await reservations.get(keyId, Availability)).errorOption:
if error of NotExistsError:
Expand Down Expand Up @@ -462,10 +465,10 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) =
headers.add(("Access-Control-Allow-Origin", corsOrigin))
headers.add(("Access-Control-Allow-Methods", "POST, OPTIONS"))
headers.add(("Access-Control-Max-Age", "86400"))

try:
without contracts =? node.contracts.client:
return RestApiResponse.error(Http503, "Purchasing unavailable", headers = headers)
return RestApiResponse.error(Http503, "Persistence is not enabled", headers = headers)

without cid =? cid.tryGet.catch, error:
return RestApiResponse.error(Http400, error.msg, headers = headers)
Expand All @@ -475,8 +478,11 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) =
without params =? StorageRequestParams.fromJson(body), error:
return RestApiResponse.error(Http400, error.msg, headers = headers)

let nodes = params.nodes |? 1
let tolerance = params.tolerance |? 0
let nodes = params.nodes |? 3
let tolerance = params.tolerance |? 1

if tolerance == 0:
return RestApiResponse.error(Http400, "Tolerance needs to be bigger then zero", headers = headers)

# prevent underflow
if tolerance > nodes:
Expand Down Expand Up @@ -524,7 +530,7 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) =

try:
without contracts =? node.contracts.client:
return RestApiResponse.error(Http503, "Purchasing unavailable")
return RestApiResponse.error(Http503, "Persistence is not enabled")

without id =? id.tryGet.catch, error:
return RestApiResponse.error(Http400, error.msg)
Expand All @@ -549,7 +555,7 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) =
"/api/codex/v1/storage/purchases") do () -> RestApiResponse:
try:
without contracts =? node.contracts.client:
return RestApiResponse.error(Http503, "Purchasing unavailable")
return RestApiResponse.error(Http503, "Persistence is not enabled")

let purchaseIds = contracts.purchasing.getPurchaseIds()
return RestApiResponse.response($ %purchaseIds, contentType="application/json")
Expand Down
2 changes: 2 additions & 0 deletions codex/rest/json.nim
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,8 @@ type
state* {.serialize.}: string
requestId* {.serialize.}: RequestId
slotIndex* {.serialize.}: UInt256
request* {.serialize.}: ?StorageRequest
reservation* {.serialize.}: ?Reservation

RestContent* = object
cid* {.serialize.}: Cid
Expand Down
14 changes: 9 additions & 5 deletions codex/sales.nim
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ proc filled(
processing.complete()

proc processSlot(sales: Sales, item: SlotQueueItem, done: Future[void]) =
debug "processing slot from queue", requestId = item.requestId,
debug "Processing slot from queue", requestId = item.requestId,
slot = item.slotIndex

let agent = newSalesAgent(
Expand All @@ -202,13 +202,17 @@ proc processSlot(sales: Sales, item: SlotQueueItem, done: Future[void]) =
proc deleteInactiveReservations(sales: Sales, activeSlots: seq[Slot]) {.async.} =
let reservations = sales.context.reservations
without reservs =? await reservations.all(Reservation):
info "no unused reservations found for deletion"
return

let unused = reservs.filter(r => (
let slotId = slotId(r.requestId, r.slotIndex)
not activeSlots.any(slot => slot.id == slotId)
))
info "found unused reservations for deletion", unused = unused.len

if unused.len == 0:
return

info "Found unused reservations for deletion", unused = unused.len

for reservation in unused:

Expand All @@ -219,9 +223,9 @@ proc deleteInactiveReservations(sales: Sales, activeSlots: seq[Slot]) {.async.}
if err =? (await reservations.deleteReservation(
reservation.id, reservation.availabilityId
)).errorOption:
error "failed to delete unused reservation", error = err.msg
error "Failed to delete unused reservation", error = err.msg
else:
trace "deleted unused reservation"
trace "Deleted unused reservation"

proc mySlots*(sales: Sales): Future[seq[Slot]] {.async.} =
let market = sales.context.market
Expand Down
4 changes: 2 additions & 2 deletions codex/sales/reservations.nim
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
## |----------------------------------------| |--------------------------------------|
## | UInt256 | totalSize | | | UInt256 | size | |
## |----------------------------------------| |--------------------------------------|
## | UInt256 | freeSize | | | SlotId | slotId | |
## | UInt256 | freeSize | | | UInt256 | slotIndex | |
## |----------------------------------------| +--------------------------------------+
## | UInt256 | duration | |
## |----------------------------------------|
Expand Down Expand Up @@ -65,7 +65,7 @@ type
totalSize* {.serialize.}: UInt256
freeSize* {.serialize.}: UInt256
duration* {.serialize.}: UInt256
minPrice* {.serialize.}: UInt256
minPrice* {.serialize.}: UInt256 # minimal price paid for the whole hosted slot for the request's duration
maxCollateral* {.serialize.}: UInt256
Reservation* = ref object
id* {.serialize.}: ReservationId
Expand Down
4 changes: 2 additions & 2 deletions codex/sales/states/preparing.nim
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,11 @@ method run*(state: SalePreparing, machine: Machine): Future[?State] {.async.} =
request.ask.duration,
request.ask.pricePerSlot,
request.ask.collateral):
debug "no availability found for request, ignoring"
debug "No availability found for request, ignoring"

return some State(SaleIgnored())

info "availability found for request, creating reservation"
info "Availability found for request, creating reservation"

without reservation =? await reservations.createReservation(
availability.id,
Expand Down
Loading

0 comments on commit 4b9336e

Please sign in to comment.