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.
This commit is contained in:
Eric 2024-09-23 19:06:25 +10:00
parent 4c22934d1f
commit 6e10e3d2cf
No known key found for this signature in database
9 changed files with 50 additions and 12 deletions

View File

@ -19,6 +19,7 @@ type
content* {.serialize.}: StorageContent content* {.serialize.}: StorageContent
expiry* {.serialize.}: UInt256 expiry* {.serialize.}: UInt256
nonce*: Nonce nonce*: Nonce
expansionRate* {.serialize.}: uint8
StorageAsk* = object StorageAsk* = object
slots* {.serialize.}: uint64 slots* {.serialize.}: uint64
slotSize* {.serialize.}: UInt256 slotSize* {.serialize.}: UInt256
@ -93,7 +94,8 @@ func fromTuple(_: type StorageRequest, tupl: tuple): StorageRequest =
ask: tupl[1], ask: tupl[1],
content: tupl[2], content: tupl[2],
expiry: tupl[3], expiry: tupl[3],
nonce: tupl[4] nonce: tupl[4],
expansionRate: tupl[5],
) )
func fromTuple(_: type Slot, tupl: tuple): Slot = func fromTuple(_: type Slot, tupl: tuple): Slot =

View File

@ -394,7 +394,8 @@ proc setupRequest(
tolerance: uint, tolerance: uint,
reward: UInt256, reward: UInt256,
collateral: UInt256, collateral: UInt256,
expiry: UInt256): Future[?!StorageRequest] {.async.} = expiry: UInt256,
expansionRate: uint8): Future[?!StorageRequest] {.async.} =
## Setup slots for a given dataset ## Setup slots for a given dataset
## ##
@ -411,6 +412,7 @@ proc setupRequest(
proofProbability = proofProbability proofProbability = proofProbability
collateral = collateral collateral = collateral
expiry = expiry expiry = expiry
expansionRate = expansionRate
ecK = ecK ecK = ecK
ecM = ecM ecM = ecM
@ -474,7 +476,8 @@ proc setupRequest(
cid: $manifestBlk.cid, # TODO: why string? cid: $manifestBlk.cid, # TODO: why string?
merkleRoot: verifyRoot merkleRoot: verifyRoot
), ),
expiry: expiry expiry: expiry,
expansionRate: expansionRate
) )
trace "Request created", request = $request trace "Request created", request = $request
@ -489,7 +492,8 @@ proc requestStorage*(
tolerance: uint, tolerance: uint,
reward: UInt256, reward: UInt256,
collateral: UInt256, collateral: UInt256,
expiry: UInt256): Future[?!PurchaseId] {.async.} = expiry: UInt256,
expansionRate: uint8): Future[?!PurchaseId] {.async.} =
## Initiate a request for storage sequence, this might ## Initiate a request for storage sequence, this might
## be a multistep procedure. ## be a multistep procedure.
## ##
@ -503,6 +507,7 @@ proc requestStorage*(
proofProbability = proofProbability proofProbability = proofProbability
collateral = collateral collateral = collateral
expiry = expiry.truncate(int64) expiry = expiry.truncate(int64)
expansionRate = expansionRate
now = self.clock.now now = self.clock.now
trace "Received a request for storage!" trace "Received a request for storage!"
@ -520,7 +525,8 @@ proc requestStorage*(
tolerance, tolerance,
reward, reward,
collateral, collateral,
expiry)), err: expiry,
expansionRate)), err:
trace "Unable to setup request" trace "Unable to setup request"
return failure err return failure err

View File

@ -455,6 +455,7 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) =
let nodes = params.nodes |? 1 let nodes = params.nodes |? 1
let tolerance = params.tolerance |? 0 let tolerance = params.tolerance |? 0
let expansionRate = params.expansionRate |? 60'u8
# prevent underflow # prevent underflow
if tolerance > nodes: if tolerance > nodes:
@ -473,6 +474,9 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) =
if expiry <= 0 or expiry >= params.duration: 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) 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( without purchaseId =? await node.requestStorage(
cid, cid,
params.duration, params.duration,
@ -481,7 +485,8 @@ proc initPurchasingApi(node: CodexNodeRef, router: var RestRouter) =
tolerance, tolerance,
params.reward, params.reward,
params.collateral, params.collateral,
expiry), error: expiry,
expansionRate), error:
if error of InsufficientBlocksError: if error of InsufficientBlocksError:
return RestApiResponse.error(Http400, return RestApiResponse.error(Http400,

View File

@ -20,6 +20,7 @@ type
expiry* {.serialize.}: ?UInt256 expiry* {.serialize.}: ?UInt256
nodes* {.serialize.}: ?uint nodes* {.serialize.}: ?uint
tolerance* {.serialize.}: ?uint tolerance* {.serialize.}: ?uint
expansionRate* {.serialize.}: ?uint8
RestPurchase* = object RestPurchase* = object
requestId* {.serialize.}: RequestId requestId* {.serialize.}: RequestId

View File

@ -164,7 +164,8 @@ asyncchecksuite "Test Node - Basic":
reward = 2.u256, reward = 2.u256,
proofProbability = 3.u256, proofProbability = 3.u256,
expiry = 200.u256, expiry = 200.u256,
collateral = 200.u256)).tryGet collateral = 200.u256,
expansionRate = 100'u8)).tryGet
check: check:
(await verifiableBlock.cid in localStore) == true (await verifiableBlock.cid in localStore) == true

View File

@ -60,6 +60,7 @@ proc example*(_: type StorageRequest): StorageRequest =
merkleRoot: array[32, byte].example merkleRoot: array[32, byte].example
), ),
expiry:(60 * 60).u256, # 1 hour , expiry:(60 * 60).u256, # 1 hour ,
expansionRate: 100'u8,
nonce: Nonce.example nonce: Nonce.example
) )

View File

@ -97,7 +97,8 @@ proc requestStorageRaw*(
collateral: UInt256, collateral: UInt256,
expiry: uint = 0, expiry: uint = 0,
nodes: uint = 2, nodes: uint = 2,
tolerance: uint = 0 tolerance: uint = 0,
expansionRate: uint8 = 100
): Response = ): Response =
## Call request storage REST endpoint ## Call request storage REST endpoint
@ -109,7 +110,8 @@ proc requestStorageRaw*(
"proofProbability": proofProbability, "proofProbability": proofProbability,
"collateral": collateral, "collateral": collateral,
"nodes": nodes, "nodes": nodes,
"tolerance": tolerance "tolerance": tolerance,
"expansionRate": expansionRate
} }
if expiry != 0: if expiry != 0:
@ -126,11 +128,12 @@ proc requestStorage*(
expiry: uint, expiry: uint,
collateral: UInt256, collateral: UInt256,
nodes: uint = 2, nodes: uint = 2,
tolerance: uint = 0 tolerance: uint = 0,
expansionRate: uint8 = 100
): ?!PurchaseId = ): ?!PurchaseId =
## Call request storage REST endpoint ## 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": if response.status != "200 OK":
doAssert(false, response.body) doAssert(false, response.body)
PurchaseId.fromHex(response.body).catch PurchaseId.fromHex(response.body).catch

View File

@ -105,6 +105,25 @@ twonodessuite "REST API", debug1 = false, debug2 = false:
check responseBefore.status == "400 Bad Request" check responseBefore.status == "400 Bad Request"
check responseBefore.body == "Invalid parameters: `tolerance` cannot be greater than `nodes`" 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": test "request storage succeeds if nodes and tolerance within range":
let data = await RandomChunker.example(blocks=2) let data = await RandomChunker.example(blocks=2)
let cid = client1.upload(data).get let cid = client1.upload(data).get

@ -1 +1 @@
Subproject commit d2ba8693e772b83e80746ffadc1efc36c836caf0 Subproject commit 2331ae1f0ada27bb1a9fe61d7432033ef0ab5d81