diff --git a/codex/contracts/requests.nim b/codex/contracts/requests.nim index 1363fb9d..946b59af 100644 --- a/codex/contracts/requests.nim +++ b/codex/contracts/requests.nim @@ -19,6 +19,7 @@ type content* {.serialize.}: StorageContent expiry* {.serialize.}: UInt256 nonce*: Nonce + expansionRate* {.serialize.}: uint8 StorageAsk* = object slots* {.serialize.}: uint64 slotSize* {.serialize.}: UInt256 @@ -93,7 +94,8 @@ func fromTuple(_: type StorageRequest, tupl: tuple): StorageRequest = ask: tupl[1], content: tupl[2], expiry: tupl[3], - nonce: tupl[4] + nonce: tupl[4], + expansionRate: tupl[5], ) func fromTuple(_: type Slot, tupl: tuple): Slot = diff --git a/codex/node.nim b/codex/node.nim index 88305a08..fc6d15f8 100644 --- a/codex/node.nim +++ b/codex/node.nim @@ -394,7 +394,8 @@ proc setupRequest( tolerance: uint, reward: UInt256, collateral: UInt256, - expiry: UInt256): Future[?!StorageRequest] {.async.} = + expiry: UInt256, + expansionRate: uint8): Future[?!StorageRequest] {.async.} = ## Setup slots for a given dataset ## @@ -411,6 +412,7 @@ proc setupRequest( proofProbability = proofProbability collateral = collateral expiry = expiry + expansionRate = expansionRate ecK = ecK ecM = ecM @@ -474,7 +476,8 @@ proc setupRequest( cid: $manifestBlk.cid, # TODO: why string? merkleRoot: verifyRoot ), - expiry: expiry + expiry: expiry, + expansionRate: expansionRate ) trace "Request created", request = $request @@ -489,7 +492,8 @@ proc requestStorage*( tolerance: uint, reward: UInt256, collateral: UInt256, - expiry: UInt256): Future[?!PurchaseId] {.async.} = + expiry: UInt256, + expansionRate: uint8): Future[?!PurchaseId] {.async.} = ## Initiate a request for storage sequence, this might ## be a multistep procedure. ## @@ -503,6 +507,7 @@ proc requestStorage*( proofProbability = proofProbability collateral = collateral expiry = expiry.truncate(int64) + expansionRate = expansionRate now = self.clock.now trace "Received a request for storage!" @@ -520,7 +525,8 @@ proc requestStorage*( tolerance, reward, collateral, - expiry)), err: + expiry, + expansionRate)), err: trace "Unable to setup request" return failure err diff --git a/codex/rest/api.nim b/codex/rest/api.nim index 8197d8d4..67f7e36c 100644 --- a/codex/rest/api.nim +++ b/codex/rest/api.nim @@ -455,6 +455,7 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) = let nodes = params.nodes |? 1 let tolerance = params.tolerance |? 0 + let expansionRate = params.expansionRate |? 60'u8 # prevent underflow if tolerance > nodes: @@ -473,6 +474,9 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) = if expiry <= 0 or expiry >= params.duration: return RestApiResponse.error(Http400, "Expiry needs value bigger then zero and smaller then the request's duration", headers = headers) + if expansionRate > 100'u8: + return RestApiResponse.error(Http400, "Expansion rate must be between 0 and 100 (inclusive)", headers = headers) + without purchaseId =? await node.requestStorage( cid, params.duration, @@ -481,7 +485,8 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) = tolerance, params.reward, params.collateral, - expiry), error: + expiry, + expansionRate), error: if error of InsufficientBlocksError: return RestApiResponse.error(Http400, diff --git a/codex/rest/json.nim b/codex/rest/json.nim index fba708be..ac9a5a04 100644 --- a/codex/rest/json.nim +++ b/codex/rest/json.nim @@ -20,6 +20,7 @@ type expiry* {.serialize.}: ?UInt256 nodes* {.serialize.}: ?uint tolerance* {.serialize.}: ?uint + expansionRate* {.serialize.}: ?uint8 RestPurchase* = object requestId* {.serialize.}: RequestId diff --git a/tests/codex/node/testnode.nim b/tests/codex/node/testnode.nim index ab8317ec..0f9ef8b5 100644 --- a/tests/codex/node/testnode.nim +++ b/tests/codex/node/testnode.nim @@ -164,7 +164,8 @@ asyncchecksuite "Test Node - Basic": reward = 2.u256, proofProbability = 3.u256, expiry = 200.u256, - collateral = 200.u256)).tryGet + collateral = 200.u256, + expansionRate = 100'u8)).tryGet check: (await verifiableBlock.cid in localStore) == true diff --git a/tests/examples.nim b/tests/examples.nim index 17391e1a..28e0ac3f 100644 --- a/tests/examples.nim +++ b/tests/examples.nim @@ -60,6 +60,7 @@ proc example*(_: type StorageRequest): StorageRequest = merkleRoot: array[32, byte].example ), expiry:(60 * 60).u256, # 1 hour , + expansionRate: 100'u8, nonce: Nonce.example ) diff --git a/tests/integration/codexclient.nim b/tests/integration/codexclient.nim index d2d78b46..5aa2c8bd 100644 --- a/tests/integration/codexclient.nim +++ b/tests/integration/codexclient.nim @@ -97,7 +97,8 @@ proc requestStorageRaw*( collateral: UInt256, expiry: uint = 0, nodes: uint = 2, - tolerance: uint = 0 + tolerance: uint = 0, + expansionRate: uint8 = 100 ): Response = ## Call request storage REST endpoint @@ -109,7 +110,8 @@ proc requestStorageRaw*( "proofProbability": proofProbability, "collateral": collateral, "nodes": nodes, - "tolerance": tolerance + "tolerance": tolerance, + "expansionRate": expansionRate } if expiry != 0: @@ -126,11 +128,12 @@ proc requestStorage*( expiry: uint, collateral: UInt256, nodes: uint = 2, - tolerance: uint = 0 + tolerance: uint = 0, + expansionRate: uint8 = 100 ): ?!PurchaseId = ## Call request storage REST endpoint ## - let response = client.requestStorageRaw(cid, duration, reward, proofProbability, collateral, expiry, nodes, tolerance) + let response = client.requestStorageRaw(cid, duration, reward, proofProbability, collateral, expiry, nodes, tolerance, expansionRate) if response.status != "200 OK": doAssert(false, response.body) PurchaseId.fromHex(response.body).catch diff --git a/tests/integration/testrestapi.nim b/tests/integration/testrestapi.nim index 1834dcf2..6cc401ee 100644 --- a/tests/integration/testrestapi.nim +++ b/tests/integration/testrestapi.nim @@ -105,6 +105,25 @@ twonodessuite "REST API", debug1 = false, debug2 = false: check responseBefore.status == "400 Bad Request" check responseBefore.body == "Invalid parameters: `tolerance` cannot be greater than `nodes`" + + test "request storage fails when expansionRate is too large": + let data = await RandomChunker.example(blocks=2) + let cid = client1.upload(data).get + let response = client1.requestStorageRaw( + cid, + duration=10.u256, + reward=2.u256, + proofProbability=3.u256, + nodes=2, + tolerance=0, + collateral=200.u256, + expiry=9, + expansionRate=101) + + check: + response.status == "400 Bad Request" + response.body == "Expansion rate must be between 0 and 100 (inclusive)" + test "request storage succeeds if nodes and tolerance within range": let data = await RandomChunker.example(blocks=2) let cid = client1.upload(data).get diff --git a/vendor/codex-contracts-eth b/vendor/codex-contracts-eth index d2ba8693..2331ae1f 160000 --- a/vendor/codex-contracts-eth +++ b/vendor/codex-contracts-eth @@ -1 +1 @@ -Subproject commit d2ba8693e772b83e80746ffadc1efc36c836caf0 +Subproject commit 2331ae1f0ada27bb1a9fe61d7432033ef0ab5d81