[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
proc requestStorage*(
self: DaggerNodeRef,
cid: Cid,
ppb: uint,
duration: Duration,
nodes: uint,
tolerance: uint,
autoRenew: bool = false): Future[?!Cid] {.async.} =
proc requestStorage*(self: DaggerNodeRef,
cid: Cid,
duration: UInt256,
nodes: uint,
tolerance: uint,
maxPrice: UInt256): Future[?!Cid] {.async.} =
## Initiate a request for storage sequence, this might
## be a multistep procedure.
##
@ -224,7 +222,7 @@ proc requestStorage*(
## - Run the PoR setup on the erasure dataset
## - 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:
trace "Unable to retrieve manifest block", cid

View File

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

View File

@ -4,9 +4,21 @@ import pkg/stew/byteutils
import pkg/questionable/results
import ../sales
type
StorageRequestParams* = object
duration*: UInt256
maxPrice*: UInt256
proc fromJson*(_: type Availability, bytes: seq[byte]): ?!Availability =
let json = ?catch parseJson(string.fromBytes(bytes))
let size = ?catch UInt256.fromHex(json["size"].getStr)
let duration = ?catch UInt256.fromHex(json["duration"].getStr)
let minPrice = ?catch UInt256.fromHex(json["minPrice"].getStr)
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 pkg/asynctest
import pkg/chronos
import pkg/stew/byteutils
suite "Integration tests":
@ -43,6 +44,11 @@ suite "Integration tests":
let info2 = client.get(baseurl2 & "/info").body
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":
let url = baseurl1 & "/sales/availability"
let json = %*{"size": "0x1", "duration": "0x2", "minPrice": "0x3"}
@ -55,3 +61,10 @@ suite "Integration tests":
let response = client.get(url)
check response.status == "200 OK"
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"