From c437ccf9a76540714356c17775320ba077df6178 Mon Sep 17 00:00:00 2001 From: Arnaud Date: Fri, 21 Feb 2025 17:03:09 +0100 Subject: [PATCH] Move until validation to reservations module --- codex/rest/api.nim | 31 ++++----------------- codex/sales/reservations.nim | 8 +++++- tests/codex/helpers/mockreservations.nim | 2 +- tests/codex/sales/testreservations.nim | 15 ++++++----- tests/codex/sales/testsales.nim | 2 +- tests/integration/codexclient.nim | 4 ++- tests/integration/testmarketplace.nim | 30 +++++++++++---------- tests/integration/testrestapi.nim | 2 +- tests/integration/testsales.nim | 34 +++++++++++++++--------- 9 files changed, 63 insertions(+), 65 deletions(-) diff --git a/codex/rest/api.nim b/codex/rest/api.nim index 2a2e590f..47c34a8c 100644 --- a/codex/rest/api.nim +++ b/codex/rest/api.nim @@ -49,32 +49,6 @@ logScope: declareCounter(codex_api_uploads, "codex API uploads") declareCounter(codex_api_downloads, "codex API downloads") -proc getLongestRequestEnd( - node: CodexNodeRef, availabilityId: AvailabilityId -): Future[?!SecondsSince1970] {.async: (raises: []).} = - without contracts =? node.contracts.host: - return failure("Sales unavailable") - - let - reservations = contracts.sales.context.reservations - market = contracts.sales.context.market - - try: - without allReservations =? await reservations.all(Reservation, availabilityId): - return failure("Cannot retrieve the reservations") - - echo "all reservations is done" - let requestEnds = allReservations.mapIt(await market.getRequestEnd(it.requestId)) - - if len(requestEnds) == 0: - return success(0.SecondsSince1970) - - return success(requestEnds.max) - except CancelledError, CatchableError: - error "Error when trying to get longest request end", - error = getCurrentExceptionMsg() - return failure("Cannot retrieve the request dates") - proc validate(pattern: string, value: string): int {.gcsafe, raises: [Defect].} = 0 @@ -503,6 +477,11 @@ proc initSalesApi(node: CodexNodeRef, router: var RestRouter) = until = restAv.until |? 0, ) ), error: + if error of CancelledError: + raise error + if error of UntilOutOfBoundsError: + return RestApiResponse.error(Http422, error.msg) + return RestApiResponse.error(Http500, error.msg, headers = headers) return RestApiResponse.response( diff --git a/codex/sales/reservations.nim b/codex/sales/reservations.nim index c34ba474..f49ba0e8 100644 --- a/codex/sales/reservations.nim +++ b/codex/sales/reservations.nim @@ -482,7 +482,13 @@ method createReservation*( ) return failure(error) + if duration > SecondsSince1970.high.uint64: + error "Cannot cast duration to int64", duration = duration + let error = newException(ReservationsError, "Cannot cast duration to int64") + return failure(error) + let validUntil = times.now().utc().toTime().toUnix() + duration.SecondsSince1970 + trace "Creating reservation", availabilityId, slotSize, requestId, slotIndex, validUntil = validUntil @@ -497,7 +503,7 @@ method createReservation*( availability.freeSize -= slotSize # adjust the remaining totalRemainingCollateral - availability.totalRemainingCollateral -= slotSize.stuint(256) * collateralPerByte + availability.totalRemainingCollateral -= slotSize.u256 * collateralPerByte # update availability with reduced size trace "Updating availability with reduced size" diff --git a/tests/codex/helpers/mockreservations.nim b/tests/codex/helpers/mockreservations.nim index 788a79a4..1e72e308 100644 --- a/tests/codex/helpers/mockreservations.nim +++ b/tests/codex/helpers/mockreservations.nim @@ -28,7 +28,7 @@ method createReservation*( requestId: RequestId, slotIndex: uint64, collateralPerByte: UInt256, - duration: UInt256, + duration: uint64, ): Future[?!Reservation] {.async.} = if self.createReservationThrowBytesOutOfBoundsError: let error = newException( diff --git a/tests/codex/sales/testreservations.nim b/tests/codex/sales/testreservations.nim index 691a1273..7df30bb2 100644 --- a/tests/codex/sales/testreservations.nim +++ b/tests/codex/sales/testreservations.nim @@ -53,7 +53,7 @@ asyncchecksuite "Reservations module": proc createReservation(availability: Availability): Reservation = let size = rand(1 ..< availability.freeSize.int) let reservation = waitFor reservations.createReservation( - availability.id, size.uint64, RequestId.example, uint64.example, 1.u256 + availability.id, size.uint64, RequestId.example, uint64.example, 1.u256, 30.uint64 ) return reservation.get @@ -136,7 +136,7 @@ asyncchecksuite "Reservations module": let availability = Availability.example let created = await reservations.createReservation( availability.id, uint64.example, RequestId.example, uint64.example, 1.u256, - 30.u256, + 30.uint64, ) check created.isErr check created.error of NotExistsError @@ -149,7 +149,7 @@ asyncchecksuite "Reservations module": RequestId.example, uint64.example, UInt256.example, - UInt256.example, + 30.uint64, ) check created.isErr check created.error of BytesOutOfBoundsError @@ -163,18 +163,19 @@ asyncchecksuite "Reservations module": RequestId.example, uint64.example, UInt256.example, - UInt256.example, + 30.uint64, ) let two = reservations.createReservation( availability.id, availability.totalSize, RequestId.example, uint64.example, - UInt256.example, UInt256.example, + UInt256.example, uint64.example, ) let oneResult = await one let twoResult = await two check oneResult.isErr or twoResult.isErr + if oneResult.isErr: check oneResult.error of BytesOutOfBoundsError if twoResult.isErr: @@ -284,9 +285,9 @@ asyncchecksuite "Reservations module": check availability.until == until test "create an availability fails when trying set until with a negative value": - let totalSize = rand(100000 .. 200000).u256 + let totalSize = rand(100000 .. 200000).uint64 let example = Availability.example(collateralPerByte) - let totalCollateral = totalSize * collateralPerByte + let totalCollateral = totalSize.u256 * collateralPerByte let result = await reservations.createAvailability( totalSize, diff --git a/tests/codex/sales/testsales.nim b/tests/codex/sales/testsales.nim index aa428bbf..43f4438e 100644 --- a/tests/codex/sales/testsales.nim +++ b/tests/codex/sales/testsales.nim @@ -640,7 +640,7 @@ asyncchecksuite "Sales": createAvailability() discard await reservations.createReservation( availability.id, 100.uint64, RequestId.example, 0.uint64, UInt256.example, - UInt256.example, + 30.uint64, ) check (await reservations.all(Reservation)).get.len == 1 await sales.load() diff --git a/tests/integration/codexclient.nim b/tests/integration/codexclient.nim index ac85e11d..beb5f248 100644 --- a/tests/integration/codexclient.nim +++ b/tests/integration/codexclient.nim @@ -208,7 +208,8 @@ proc postAvailabilityRaw*( proc postAvailability*( client: CodexClient, - totalSize, duration, minPricePerBytePerSecond, totalCollateral: UInt256, + totalSize, duration: uint64, + minPricePerBytePerSecond, totalCollateral: UInt256, enabled: ?bool = bool.none, until: ?SecondsSince1970 = SecondsSince1970.none, ): ?!Availability = @@ -220,6 +221,7 @@ proc postAvailability*( enabled = enabled, until = until, ) + doAssert response.status == "201 Created", "expected 201 Created, got " & response.status & ", body: " & response.body Availability.fromJson(response.body) diff --git a/tests/integration/testmarketplace.nim b/tests/integration/testmarketplace.nim index a730c143..5fd52036 100644 --- a/tests/integration/testmarketplace.nim +++ b/tests/integration/testmarketplace.nim @@ -127,34 +127,36 @@ marketplacesuite "Marketplace": test "returns an error when trying to update the until date before an existing a request is finished", marketplaceConfig: - let size = 0xFFFFFF.u256 + let size = 0xFFFFFF.uint64 let data = await RandomChunker.example(blocks = blocks) let marketplace = Marketplace.new(Marketplace.address, ethProvider.getSigner()) let tokenAddress = await marketplace.token() let token = Erc20Token.new(tokenAddress, ethProvider.getSigner()) - let duration = 20 * 60.u256 + let duration = 20 * 60.uint64 # host makes storage available let startBalanceHost = await token.balanceOf(hostAccount) let availability = host.postAvailability( totalSize = size, - duration = 20 * 60.u256, + duration = 20 * 60.uint64, minPricePerBytePerSecond = minPricePerBytePerSecond, - totalCollateral = size * minPricePerBytePerSecond, + totalCollateral = size.u256 * minPricePerBytePerSecond, ).get # client requests storage let cid = client.upload(data).get - let id = client.requestStorage( - cid, - duration = duration, - pricePerBytePerSecond = minPricePerBytePerSecond, - proofProbability = 3.u256, - expiry = 10 * 60, - collateralPerByte = collateralPerByte, - nodes = ecNodes, - tolerance = ecTolerance, - ).get + let id = ( + await client.requestStorage( + cid, + duration = duration, + pricePerBytePerSecond = minPricePerBytePerSecond, + proofProbability = 3.u256, + expiry = 10 * 60.uint64, + collateralPerByte = collateralPerByte, + nodes = ecNodes, + tolerance = ecTolerance, + ) + ) check eventually(client.purchaseStateIs(id, "started"), timeout = 10 * 60 * 1000) let purchase = client.getPurchase(id).get diff --git a/tests/integration/testrestapi.nim b/tests/integration/testrestapi.nim index 62d0df2d..366cc3e3 100644 --- a/tests/integration/testrestapi.nim +++ b/tests/integration/testrestapi.nim @@ -33,7 +33,7 @@ twonodessuite "REST API": duration = 2.uint64, minPricePerBytePerSecond = minPricePerBytePerSecond, totalCollateral = totalCollateral, - enabled = true, + enabled = true.some, ).get let space = client1.space().tryGet() check: diff --git a/tests/integration/testsales.nim b/tests/integration/testsales.nim index 4571505d..7dcf294d 100644 --- a/tests/integration/testsales.nim +++ b/tests/integration/testsales.nim @@ -57,20 +57,20 @@ multinodesuite "Sales": check availability in host.getAvailabilities().get test "creating availability fails when until is negative", salesConfig: - let totalSize = 12.u256 + let totalSize = 12.uint64 let minPricePerBytePerSecond = 1.u256 - let totalCollateral = totalSize * minPricePerBytePerSecond + let totalCollateral = totalSize.u256 * minPricePerBytePerSecond let response = host.postAvailabilityRaw( totalSize = totalSize, - duration = 2.u256, + duration = 2.uint64, minPricePerBytePerSecond = minPricePerBytePerSecond, totalCollateral = totalCollateral, - until = cast[SecondsSince1970](-1).some, + until = -1.SecondsSince1970.some, ) check: - response.status == "400 Bad Request" - response.body == "Until parameter must be greater or equal 0. Got: -1" + response.status == "422 Unprocessable Entity" + response.body == "Cannot set until to a negative value" test "updating non-existing availability", salesConfig: let nonExistingResponse = host.patchAvailabilityRaw( @@ -131,6 +131,9 @@ multinodesuite "Sales": totalCollateral = 300.u256, ).get host.patchAvailability(availability.id, totalSize = 100000.uint64.some) + + host.restart() + let updatedAvailability = (host.getAvailabilities().get).findItem(availability).get check updatedAvailability.totalSize == 100000 check updatedAvailability.freeSize == 100000 @@ -169,10 +172,16 @@ multinodesuite "Sales": let utilizedSize = updatedAvailability.totalSize - updatedAvailability.freeSize let totalSizeResponse = host.patchAvailabilityRaw(availability.id, totalSize = (utilizedSize - 1).some) + + host.restart() + check totalSizeResponse.status == "400 Bad Request" check "totalSize must be larger then current totalSize" in totalSizeResponse.body host.patchAvailability(availability.id, totalSize = (originalSize + 20000).some) + + host.restart() + let newUpdatedAvailability = (host.getAvailabilities().get).findItem(availability).get check newUpdatedAvailability.totalSize == originalSize + 20000 @@ -180,16 +189,15 @@ multinodesuite "Sales": test "updating availability fails with until negative", salesConfig: let availability = host.postAvailability( - totalSize = 140000.u256, - duration = 200.u256, + totalSize = 140000.uint64, + duration = 200.uint64, minPricePerBytePerSecond = 3.u256, totalCollateral = 300.u256, ).get - let response = host.patchAvailabilityRaw( - availability.id, until = cast[SecondsSince1970](-1).some - ) + let response = + host.patchAvailabilityRaw(availability.id, until = -1.SecondsSince1970.some) check: - response.status == "400 Bad Request" - response.body == "Until parameter must be greater or equal 0. Got: -1" + response.status == "422 Unprocessable Entity" + response.body == "Cannot set until to a negative value"