chore(marketplace) - fix the http error codes when validating the availability requests (#1104)

* Use 422 http code when there is a validation error

* Update the open api description

* Fix typo

* Add more tests for total size

* Catch CancelledError because TrackedFuture raise no error

* Split rest api validation test to a new file

* Change the way of testing negative numbers

* Rename client variable and fix test status code

* Try to reduce the number of requests in CI when asserting in tests

* Fix rebase and remove safeEventually
This commit is contained in:
Arnaud 2025-03-24 16:47:05 +01:00 committed by GitHub
parent 709a8648fd
commit a0d6fbaf02
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
10 changed files with 418 additions and 246 deletions

View File

@ -475,7 +475,7 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
if restAv.totalSize == 0:
return RestApiResponse.error(
Http400, "Total size must be larger then zero", headers = headers
Http422, "Total size must be larger then zero", headers = headers
)
if not reservations.hasAvailable(restAv.totalSize):
@ -548,17 +548,23 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) =
return RestApiResponse.error(Http500, error.msg)
if isSome restAv.freeSize:
return RestApiResponse.error(Http400, "Updating freeSize is not allowed")
return RestApiResponse.error(Http422, "Updating freeSize is not allowed")
if size =? restAv.totalSize:
if size == 0:
return RestApiResponse.error(Http422, "Total size must be larger then zero")
# we don't allow lowering the totalSize bellow currently utilized size
if size < (availability.totalSize - availability.freeSize):
return RestApiResponse.error(
Http400,
Http422,
"New totalSize must be larger then current totalSize - freeSize, which is currently: " &
$(availability.totalSize - availability.freeSize),
)
if not reservations.hasAvailable(size):
return RestApiResponse.error(Http422, "Not enough storage quota")
availability.freeSize += size - availability.totalSize
availability.totalSize = size

View File

@ -374,13 +374,13 @@ proc onSlotFreed(sales: Sales, requestId: RequestId, slotIndex: uint64) =
if err =? queue.push(slotQueueItem).errorOption:
if err of SlotQueueItemExistsError:
error "Failed to push item to queue becaue it already exists",
error "Failed to push item to queue because it already exists",
error = err.msgDetail
elif err of QueueNotRunningError:
warn "Failed to push item to queue becaue queue is not running",
warn "Failed to push item to queue because queue is not running",
error = err.msgDetail
except CatchableError as e:
warn "Failed to add slot to queue", error = e.msg
except CancelledError as e:
trace "sales.addSlotToQueue was cancelled"
# We could get rid of this by adding the storage ask in the SlotFreed event,
# so we would not need to call getRequest to get the collateralPerSlot.

View File

@ -704,7 +704,7 @@ paths:
"400":
description: Invalid data input
"422":
description: Not enough node's storage quota available
description: The provided parameters did not pass validation
"500":
description: Error reserving availability
"503":
@ -737,7 +737,7 @@ paths:
"404":
description: Availability not found
"422":
description: Not enough node's storage quota available
description: The provided parameters did not pass validation
"500":
description: Error reserving availability
"503":

View File

@ -1,7 +1,7 @@
import helpers/multisetup
import helpers/trackers
import helpers/templeveldb
import std/times
import std/sequtils, chronos
export multisetup, trackers, templeveldb

View File

@ -45,7 +45,7 @@ proc request(
).get
.send()
proc post(
proc post*(
self: CodexClient,
url: string,
body: string = "",
@ -69,7 +69,7 @@ proc delete(
.} =
return self.request(MethodDelete, url, headers = headers)
proc patch(
proc patch*(
self: CodexClient,
url: string,
body: string = "",
@ -290,11 +290,11 @@ proc getSalesAgent*(
except CatchableError as e:
return failure e.msg
proc postAvailability*(
proc postAvailabilityRaw*(
client: CodexClient,
totalSize, duration: uint64,
minPricePerBytePerSecond, totalCollateral: UInt256,
): Future[?!Availability] {.async: (raises: [CancelledError, HttpError]).} =
): Future[HttpClientResponseRef] {.async: (raises: [CancelledError, HttpError]).} =
## Post sales availability endpoint
##
let url = client.baseurl & "/sales/availability"
@ -305,7 +305,17 @@ proc postAvailability*(
"minPricePerBytePerSecond": minPricePerBytePerSecond,
"totalCollateral": totalCollateral,
}
let response = await client.post(url, $json)
return await client.post(url, $json)
proc postAvailability*(
client: CodexClient,
totalSize, duration: uint64,
minPricePerBytePerSecond, totalCollateral: UInt256,
): Future[?!Availability] {.async: (raises: [CancelledError, HttpError]).} =
let response = await client.postAvailabilityRaw(
totalSize, duration, minPricePerBytePerSecond, totalCollateral
)
let body = await response.body
doAssert response.status == 201,
@ -389,3 +399,6 @@ proc requestId*(
client: CodexClient, id: PurchaseId
): Future[?RequestId] {.async: (raises: [CancelledError, HttpError]).} =
return (await client.getPurchase(id)).option .? requestId
proc buildUrl*(client: CodexClient, path: string): string =
return client.baseurl & path

View File

@ -37,10 +37,12 @@ type
MultiNodeSuiteError = object of CatchableError
const jsonRpcProviderUrl* = "http://127.0.0.1:8545"
proc raiseMultiNodeSuiteError(msg: string) =
raise newException(MultiNodeSuiteError, msg)
proc nextFreePort(startPort: int): Future[int] {.async.} =
proc nextFreePort*(startPort: int): Future[int] {.async.} =
proc client(server: StreamServer, transp: StreamTransport) {.async.} =
await transp.closeWait()
@ -60,6 +62,15 @@ proc nextFreePort(startPort: int): Future[int] {.async.} =
trace "port is not free", port
inc port
proc sanitize(pathSegment: string): string =
var sanitized = pathSegment
for invalid in invalidFilenameChars.items:
sanitized = sanitized.replace(invalid, '_').replace(' ', '_')
sanitized
proc getTempDirName*(starttime: string, role: Role, roleIdx: int): string =
getTempDir() / "Codex" / sanitize($starttime) / sanitize($role & "_" & $roleIdx)
template multinodesuite*(name: string, body: untyped) =
asyncchecksuite name:
# Following the problem described here:
@ -82,7 +93,6 @@ template multinodesuite*(name: string, body: untyped) =
# .withEthProvider("ws://localhost:8545")
# .some,
# ...
let jsonRpcProviderUrl = "http://127.0.0.1:8545"
var running {.inject, used.}: seq[RunningNode]
var bootstrapNodes: seq[string]
let starttime = now().format("yyyy-MM-dd'_'HH:mm:ss")
@ -148,8 +158,7 @@ template multinodesuite*(name: string, body: untyped) =
raiseMultiNodeSuiteError "Cannot start node at nodeIdx " & $nodeIdx &
", not enough eth accounts."
let datadir =
getTempDir() / "Codex" / sanitize($starttime) / sanitize($role & "_" & $roleIdx)
let datadir = getTempDirName(starttime, role, roleIdx)
try:
if config.logFile.isSome:

View File

@ -55,25 +55,6 @@ twonodessuite "REST API":
check:
[cid1, cid2].allIt(it in list.content.mapIt(it.cid))
test "request storage fails for datasets that are too small", twoNodesConfig:
let cid = (await client1.upload("some file contents")).get
let response = (
await client1.requestStorageRaw(
cid,
duration = 10.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
collateralPerByte = 1.u256,
expiry = 9.uint64,
)
)
check:
response.status == 422
(await response.body) ==
"Dataset too small for erasure parameters, need at least " &
$(2 * DefaultBlockSize.int) & " bytes"
test "request storage succeeds for sufficiently sized datasets", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
@ -91,176 +72,6 @@ twonodessuite "REST API":
check:
response.status == 200
test "request storage fails if tolerance is zero", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 0
var responseBefore = (
await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
test "request storage fails if duration exceeds limit", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
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
let proofProbability = 3.u256
let expiry = 30.uint
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 2
let pricePerBytePerSecond = 1.u256
var responseBefore = (
await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check "Duration exceeds limit of" in (await responseBefore.body)
test "request storage fails if nodes and tolerance aren't correct", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)]
for ecParam in ecParams:
let (nodes, tolerance) = ecParam
var responseBefore = (
await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check (await responseBefore.body) ==
"Invalid parameters: parameters must satify `1 < (nodes - tolerance) ≥ tolerance`"
test "request storage fails if tolerance > nodes (underflow protection)",
twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let ecParams = @[(0, 1), (1, 2), (2, 3)]
for ecParam in ecParams:
let (nodes, tolerance) = ecParam
var responseBefore = (
await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check (await responseBefore.body) ==
"Invalid parameters: `tolerance` cannot be greater than `nodes`"
test "request storage fails if expiry is zero", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 0.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) ==
"Expiry must be greater than zero and less than the request's duration"
test "request storage fails if proof probability is zero", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 0.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) == "Proof probability must be greater than zero"
test "request storage fails if collareral per byte is zero", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 0.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) == "Collateral per byte must be greater than zero"
test "request storage fails if price per byte per second is zero", twoNodesConfig:
let data = await RandomChunker.example(blocks = 2)
let cid = (await client1.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 0.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client1.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) ==
"Price per byte per second must be greater than zero"
for ecParams in @[
(minBlocks: 2, nodes: 3, tolerance: 1), (minBlocks: 3, nodes: 5, tolerance: 2)
]:
@ -306,20 +117,6 @@ twonodessuite "REST API":
check response.status == 200
check (await response.body) != ""
test "upload fails if content disposition contains bad filename", twoNodesConfig:
let headers = @[("Content-Disposition", "attachment; filename=\"exam*ple.txt\"")]
let response = await client1.uploadRaw("some file contents", headers)
check response.status == 422
check (await response.body) == "The filename is not valid."
test "upload fails if content type is invalid", twoNodesConfig:
let headers = @[("Content-Type", "hello/world")]
let response = await client1.uploadRaw("some file contents", headers)
check response.status == 422
check (await response.body) == "The MIME type 'hello/world' is not valid."
test "node retrieve the metadata", twoNodesConfig:
let headers =
@[

View File

@ -0,0 +1,368 @@
import std/httpclient
import std/times
import pkg/ethers
import pkg/codex/manifest
import pkg/codex/conf
import pkg/codex/contracts
from pkg/codex/stores/repostore/types import DefaultQuotaBytes
import ../asynctest
import ../checktest
import ../examples
import ../codex/examples
import ./codexconfig
import ./codexprocess
from ./multinodes import Role, getTempDirName, jsonRpcProviderUrl, nextFreePort
# This suite allows to run fast the basic rest api validation.
# It starts only one node for all the checks in order to speed up
# the execution.
asyncchecksuite "Rest API validation":
var node: CodexProcess
var config = CodexConfigs.init(nodes = 1).configs[0]
let starttime = now().format("yyyy-MM-dd'_'HH:mm:ss")
let nodexIdx = 0
let datadir = getTempDirName(starttime, Role.Client, nodexIdx)
config.addCliOption("--api-port", $(waitFor nextFreePort(8081)))
config.addCliOption("--data-dir", datadir)
config.addCliOption("--nat", "none")
config.addCliOption("--listen-addrs", "/ip4/127.0.0.1/tcp/0")
config.addCliOption("--disc-port", $(waitFor nextFreePort(8081)))
config.addCliOption(StartUpCmd.persistence, "--eth-provider", jsonRpcProviderUrl)
config.addCliOption(StartUpCmd.persistence, "--eth-account", $EthAddress.example)
node =
waitFor CodexProcess.startNode(config.cliArgs, config.debugEnabled, $Role.Client)
waitFor node.waitUntilStarted()
let client = node.client()
test "should return 422 when attempting delete of non-existing dataset":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 0
var responseBefore = await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
test "request storage fails for datasets that are too small":
let cid = (await client.upload("some file contents")).get
let response = (
await client.requestStorageRaw(
cid,
duration = 10.uint64,
pricePerBytePerSecond = 1.u256,
proofProbability = 3.u256,
collateralPerByte = 1.u256,
expiry = 9.uint64,
)
)
check:
response.status == 422
(await response.body) ==
"Dataset too small for erasure parameters, need at least " &
$(2 * DefaultBlockSize.int) & " bytes"
test "request storage fails if nodes and tolerance aren't correct":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let ecParams = @[(1, 1), (2, 1), (3, 2), (3, 3)]
for ecParam in ecParams:
let (nodes, tolerance) = ecParam
var responseBefore = (
await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check (await responseBefore.body) ==
"Invalid parameters: parameters must satify `1 < (nodes - tolerance) ≥ tolerance`"
test "request storage fails if tolerance > nodes (underflow protection)":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 0
var responseBefore = (
await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
test "upload fails if content disposition contains bad filename":
let headers = @[("Content-Disposition", "attachment; filename=\"exam*ple.txt\"")]
let response = await client.uploadRaw("some file contents", headers)
check response.status == 422
check (await response.body) == "The filename is not valid."
test "upload fails if content type is invalid":
let headers = @[("Content-Type", "hello/world")]
let response = await client.uploadRaw("some file contents", headers)
check response.status == 422
check (await response.body) == "The MIME type 'hello/world' is not valid."
test "updating non-existing availability":
let nonExistingResponse = await client.patchAvailabilityRaw(
AvailabilityId.example,
duration = 100.uint64.some,
minPricePerBytePerSecond = 2.u256.some,
totalCollateral = 200.u256.some,
)
check nonExistingResponse.status == 404
test "updating availability - freeSize is not allowed to be changed":
let availability = (
await client.postAvailability(
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
)
).get
let freeSizeResponse =
await client.patchAvailabilityRaw(availability.id, freeSize = 110000.uint64.some)
check freeSizeResponse.status == 422
check "not allowed" in (await freeSizeResponse.body)
test "creating availability above the node quota returns 422":
let response = await client.postAvailabilityRaw(
totalSize = 24000000000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
)
check response.status == 422
check (await response.body) == "Not enough storage quota"
test "updating availability above the node quota returns 422":
let availability = (
await client.postAvailability(
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
)
).get
let response = await client.patchAvailabilityRaw(
availability.id, totalSize = 24000000000.uint64.some
)
check response.status == 422
check (await response.body) == "Not enough storage quota"
test "creating availability when total size is zero returns 422":
let response = await client.postAvailabilityRaw(
totalSize = 0.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
)
check response.status == 422
check (await response.body) == "Total size must be larger then zero"
test "updating availability when total size is zero returns 422":
let availability = (
await client.postAvailability(
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
)
).get
let response =
await client.patchAvailabilityRaw(availability.id, totalSize = 0.uint64.some)
check response.status == 422
check (await response.body) == "Total size must be larger then zero"
test "creating availability when total size is negative returns 422":
let json =
%*{
"totalSize": "-1",
"duration": "200",
"minPricePerBytePerSecond": "3",
"totalCollateral": "300",
}
let response = await client.post(client.buildUrl("/sales/availability"), $json)
check response.status == 400
check (await response.body) == "Parsed integer outside of valid range"
test "updating availability when total size is negative returns 422":
let availability = (
await client.postAvailability(
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
)
).get
let json = %*{"totalSize": "-1"}
let response = await client.patch(
client.buildUrl("/sales/availability/") & $availability.id, $json
)
check response.status == 400
check (await response.body) == "Parsed integer outside of valid range"
test "request storage fails if tolerance is zero":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 0
var responseBefore = (
await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check (await responseBefore.body) == "Tolerance needs to be bigger then zero"
test "request storage fails if duration exceeds limit":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
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
let proofProbability = 3.u256
let expiry = 30.uint
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 2
let pricePerBytePerSecond = 1.u256
var responseBefore = (
await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte,
expiry, nodes.uint, tolerance.uint,
)
)
check responseBefore.status == 422
check "Duration exceeds limit of" in (await responseBefore.body)
test "request storage fails if expiry is zero":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 0.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) ==
"Expiry must be greater than zero and less than the request's duration"
test "request storage fails if proof probability is zero":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 0.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) == "Proof probability must be greater than zero"
test "request storage fails if price per byte per second is zero":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 0.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 1.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) ==
"Price per byte per second must be greater than zero"
test "request storage fails if collareral per byte is zero":
let data = await RandomChunker.example(blocks = 2)
let cid = (await client.upload(data)).get
let duration = 100.uint64
let pricePerBytePerSecond = 1.u256
let proofProbability = 3.u256
let expiry = 30.uint64
let collateralPerByte = 0.u256
let nodes = 3
let tolerance = 1
var responseBefore = await client.requestStorageRaw(
cid, duration, pricePerBytePerSecond, proofProbability, collateralPerByte, expiry,
nodes.uint, tolerance.uint,
)
check responseBefore.status == 422
check (await responseBefore.body) == "Collateral per byte must be greater than zero"
waitFor node.stop()
node.removeDataDir()

View File

@ -1,5 +1,6 @@
import std/httpclient
import pkg/codex/contracts
from pkg/codex/stores/repostore/types import DefaultQuotaBytes
import ./twonodes
import ../codex/examples
import ../contracts/time
@ -69,15 +70,6 @@ multinodesuite "Sales":
).get
check availability in (await host.getAvailabilities()).get
test "updating non-existing availability", salesConfig:
let nonExistingResponse = await host.patchAvailabilityRaw(
AvailabilityId.example,
duration = 100.uint64.some,
minPricePerBytePerSecond = 2.u256.some,
totalCollateral = 200.u256.some,
)
check nonExistingResponse.status == 404
test "updating availability", salesConfig:
let availability = (
await host.postAvailability(
@ -103,20 +95,6 @@ multinodesuite "Sales":
check updatedAvailability.totalSize == 140000.uint64
check updatedAvailability.freeSize == 140000.uint64
test "updating availability - freeSize is not allowed to be changed", salesConfig:
let availability = (
await host.postAvailability(
totalSize = 140000.uint64,
duration = 200.uint64,
minPricePerBytePerSecond = 3.u256,
totalCollateral = 300.u256,
)
).get
let freeSizeResponse =
await host.patchAvailabilityRaw(availability.id, freeSize = 110000.uint64.some)
check freeSizeResponse.status == 400
check "not allowed" in (await freeSizeResponse.body)
test "updating availability - updating totalSize", salesConfig:
let availability = (
await host.postAvailability(
@ -176,7 +154,7 @@ multinodesuite "Sales":
availability.id, totalSize = (utilizedSize - 1).some
)
)
check totalSizeResponse.status == 400
check totalSizeResponse.status == 422
check "totalSize must be larger then current totalSize" in
(await totalSizeResponse.body)

View File

@ -1,5 +1,6 @@
import ./integration/testcli
import ./integration/testrestapi
import ./integration/testrestapivalidation
import ./integration/testupdownload
import ./integration/testsales
import ./integration/testpurchasing