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:
parent
4c22934d1f
commit
6e10e3d2cf
|
@ -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 =
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
Loading…
Reference in New Issue