[rest api] submit storage request parameters as json

This commit is contained in:
Mark Spanbroek 2022-05-10 14:13:39 +02:00 committed by markspanbroek
parent fec9ad8141
commit 7d03e83bfc
4 changed files with 51 additions and 83 deletions

View File

@ -207,14 +207,12 @@ proc store*(
return manifest.cid.success return manifest.cid.success
proc requestStorage*( proc requestStorage*(self: DaggerNodeRef,
self: DaggerNodeRef,
cid: Cid, cid: Cid,
ppb: uint, duration: UInt256,
duration: Duration,
nodes: uint, nodes: uint,
tolerance: uint, tolerance: uint,
autoRenew: bool = false): Future[?!Cid] {.async.} = maxPrice: UInt256): Future[?!Cid] {.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.
## ##
@ -224,7 +222,7 @@ proc requestStorage*(
## - Run the PoR setup on the erasure dataset ## - Run the PoR setup on the erasure dataset
## - Call into the marketplace and purchasing contracts ## - Call into the marketplace and purchasing contracts
## ##
trace "Received a request for storage!", cid, ppb, duration, nodes, tolerance, autoRenew trace "Received a request for storage!", cid, duration, nodes, tolerance, maxPrice
without blk =? (await self.blockStore.getBlock(cid)), error: without blk =? (await self.blockStore.getBlock(cid)), error:
trace "Unable to retrieve manifest block", cid trace "Unable to retrieve manifest block", cid

View File

@ -175,90 +175,35 @@ proc initRestApi*(node: DaggerNodeRef, conf: DaggerConf): RestRouter =
if not stream.isNil: if not stream.isNil:
await stream.close() await stream.close()
router.api( router.rawApi(
MethodPost, MethodPost,
"/api/dagger/v1/storage/request/{cid}") do ( "/api/dagger/v1/storage/request/{cid}") do (cid: Cid) -> RestApiResponse:
cid: Cid,
ppb: Option[uint],
duration: Option[Duration],
nodes: Option[uint],
loss: Option[uint],
renew: Option[bool]) -> RestApiResponse:
## Create a request for storage ## Create a request for storage
## ##
## Cid - the cid of the previously uploaded dataset ## cid - the cid of a previously uploaded dataset
## ppb - the price per byte the client is willing to pay
## duration - the duration of the contract ## duration - the duration of the contract
## nodeCount - the total amount of the nodes storing the dataset, including `lossTolerance` ## maxPrice - the maximum price the client is willing to pay
## lossTolerance - the number of nodes losses the user is willing to tolerate
## autoRenew - should the contract be autorenewed -
## will fail unless the user has enough funds lockedup
##
var # TODO: store on multiple nodes
cid = let nodes: uint = 1
if cid.isErr: let tolerance: uint = 0
return RestApiResponse.error(Http400, $cid.error())
else:
cid.get()
ppb = without cid =? cid.tryGet.catch, error:
if ppb.isNone: return RestApiResponse.error(Http400, error.msg)
return RestApiResponse.error(Http400, "Missing ppb")
else:
if ppb.get().isErr:
return RestApiResponse.error(Http500, $ppb.get().error)
else:
ppb.get().get()
duration = let body = await request.getBody()
if duration.isNone:
return RestApiResponse.error(Http400, "Missing duration")
else:
if duration.get().isErr:
return RestApiResponse.error(Http500, $duration.get().error)
else:
duration.get().get()
nodes = without params =? StorageRequestParams.fromJson(body), error:
if nodes.isNone: return RestApiResponse.error(Http400, error.msg)
return RestApiResponse.error(Http400, "Missing node count")
else:
if nodes.get().isErr:
return RestApiResponse.error(Http500, $nodes.get().error)
else:
nodes.get().get()
loss = without storageCid =? await node.requestStorage(cid,
if loss.isNone: params.duration,
return RestApiResponse.error(Http400, "Missing loss tolerance")
else:
if loss.get().isErr:
return RestApiResponse.error(Http500, $loss.get().error)
else:
loss.get().get()
renew = if renew.isNone:
false
else:
if renew.get().isErr:
return RestApiResponse.error(Http500, $renew.get().error)
else:
renew.get().get()
try:
without storageCid =? (await node.requestStorage(
cid,
ppb,
duration,
nodes, nodes,
loss, tolerance,
renew)), error: params.maxPrice), error:
return RestApiResponse.error(Http500, error.msg) return RestApiResponse.error(Http500, error.msg)
return RestApiResponse.response($storageCid) return RestApiResponse.response($storageCid)
except CatchableError as exc:
return RestApiResponse.error(Http500, exc.msg)
router.rawApi( router.rawApi(
MethodPost, MethodPost,

View File

@ -4,9 +4,21 @@ import pkg/stew/byteutils
import pkg/questionable/results import pkg/questionable/results
import ../sales import ../sales
type
StorageRequestParams* = object
duration*: UInt256
maxPrice*: UInt256
proc fromJson*(_: type Availability, bytes: seq[byte]): ?!Availability = proc fromJson*(_: type Availability, bytes: seq[byte]): ?!Availability =
let json = ?catch parseJson(string.fromBytes(bytes)) let json = ?catch parseJson(string.fromBytes(bytes))
let size = ?catch UInt256.fromHex(json["size"].getStr) let size = ?catch UInt256.fromHex(json["size"].getStr)
let duration = ?catch UInt256.fromHex(json["duration"].getStr) let duration = ?catch UInt256.fromHex(json["duration"].getStr)
let minPrice = ?catch UInt256.fromHex(json["minPrice"].getStr) let minPrice = ?catch UInt256.fromHex(json["minPrice"].getStr)
success Availability.init(size, duration, minPrice) success Availability.init(size, duration, minPrice)
proc fromJson*(_: type StorageRequestParams,
bytes: seq[byte]): ?! StorageRequestParams =
let json = ?catch parseJson(string.fromBytes(bytes))
let duration = ?catch UInt256.fromHex(json["duration"].getStr)
let maxPrice = ?catch UInt256.fromHex(json["maxPrice"].getStr)
success StorageRequestParams(duration: duration, maxPrice: maxPrice)

View File

@ -6,6 +6,7 @@ import std/httpclient
import std/json import std/json
import pkg/asynctest import pkg/asynctest
import pkg/chronos import pkg/chronos
import pkg/stew/byteutils
suite "Integration tests": suite "Integration tests":
@ -43,6 +44,11 @@ suite "Integration tests":
let info2 = client.get(baseurl2 & "/info").body let info2 = client.get(baseurl2 & "/info").body
check info1 != info2 check info1 != info2
test "node accepts file uploads":
let url = baseurl1 & "/upload"
let response = client.post(url, "some file contents")
check response.status == "200 OK"
test "node handles new storage availability": test "node handles new storage availability":
let url = baseurl1 & "/sales/availability" let url = baseurl1 & "/sales/availability"
let json = %*{"size": "0x1", "duration": "0x2", "minPrice": "0x3"} let json = %*{"size": "0x1", "duration": "0x2", "minPrice": "0x3"}
@ -55,3 +61,10 @@ suite "Integration tests":
let response = client.get(url) let response = client.get(url)
check response.status == "200 OK" check response.status == "200 OK"
check parseJson(response.body) == %*[availability] check parseJson(response.body) == %*[availability]
test "node handles storage request":
let cid = client.post(baseurl1 & "/upload", "some file contents").body
let url = baseurl1 & "/storage/request/" & cid
let json = %*{"duration": "0x1", "maxPrice": "0x2"}
let response = client.post(url, $json)
check response.status == "200 OK"