From 6e10e3d2cfdea28dd829ab68d9670eb444dee220 Mon Sep 17 00:00:00 2001 From: Eric <5089238+emizzle@users.noreply.github.com> Date: Mon, 23 Sep 2024 19:06:25 +1000 Subject: [PATCH] feat(slot-reservations): Add expansionRate parameter to support contract changes Adds `expansionRate` field to the `StorageRequest` object, to mirror the object in the contracts. The CodexClient api module uses a default value of 100, which means that all SPs will be available to reserve slots immediately, when the functionality is finally implemented. It was chosen to provide as little disruption to existing as possible, and may change in the future. The default value for the REST API endpoint was 60, meaning 60% of the total time before expiry will have all addresses eligible to fill the slot. --- codex/contracts/requests.nim | 4 +++- codex/node.nim | 14 ++++++++++---- codex/rest/api.nim | 7 ++++++- codex/rest/json.nim | 1 + tests/codex/node/testnode.nim | 3 ++- tests/examples.nim | 1 + tests/integration/codexclient.nim | 11 +++++++---- tests/integration/testrestapi.nim | 19 +++++++++++++++++++ vendor/codex-contracts-eth | 2 +- 9 files changed, 50 insertions(+), 12 deletions(-) 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