Skip to content

Commit 6e55e37

Browse files
committed
fix(sales): set correct block expiry
Previously we used request.expiry as the block expiry, but the former is a duration in seconds, whereas the latter is a timestamp
1 parent 80a38e8 commit 6e55e37

File tree

10 files changed

+146
-107
lines changed

10 files changed

+146
-107
lines changed

codex/node.nim

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -623,6 +623,7 @@ proc requestStorage*(
623623
proc onStore(
624624
self: CodexNodeRef,
625625
request: StorageRequest,
626+
expiry: SecondsSince1970,
626627
slotIdx: uint64,
627628
blocksCb: BlocksCb,
628629
isRepairing: bool = false,
@@ -651,8 +652,6 @@ proc onStore(
651652
trace "Unable to create slots builder", err = err.msg
652653
return failure(err)
653654

654-
let expiry = request.expiry
655-
656655
if slotIdx > manifest.slotRoots.high.uint64:
657656
trace "Slot index not in manifest", slotIdx
658657
return failure(newException(CodexError, "Slot index not in manifest"))
@@ -663,7 +662,7 @@ proc onStore(
663662
trace "Updating expiry for blocks", blocks = blocks.len
664663

665664
let ensureExpiryFutures =
666-
blocks.mapIt(self.networkStore.ensureExpiry(it.cid, expiry.toSecondsSince1970))
665+
blocks.mapIt(self.networkStore.ensureExpiry(it.cid, expiry))
667666

668667
let res = await allFinishedFailed[?!void](ensureExpiryFutures)
669668
if res.failure.len > 0:
@@ -789,11 +788,12 @@ proc start*(self: CodexNodeRef) {.async.} =
789788
if hostContracts =? self.contracts.host:
790789
hostContracts.sales.onStore = proc(
791790
request: StorageRequest,
791+
expiry: SecondsSince1970,
792792
slot: uint64,
793793
onBatch: BatchProc,
794794
isRepairing: bool = false,
795795
): Future[?!void] {.async: (raw: true, raises: [CancelledError]).} =
796-
self.onStore(request, slot, onBatch, isRepairing)
796+
self.onStore(request, expiry, slot, onBatch, isRepairing)
797797

798798
hostContracts.sales.onExpiryUpdate = proc(
799799
rootCid: Cid, expiry: SecondsSince1970

codex/sales/salescontext.nim

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,11 @@ type
2828
gcsafe, async: (raises: [CancelledError])
2929
.}
3030
OnStore* = proc(
31-
request: StorageRequest, slot: uint64, blocksCb: BlocksCb, isRepairing: bool
31+
request: StorageRequest,
32+
expiry: SecondsSince1970,
33+
slot: uint64,
34+
blocksCb: BlocksCb,
35+
isRepairing: bool,
3236
): Future[?!void] {.gcsafe, async: (raises: [CancelledError]).}
3337
OnProve* = proc(slot: Slot, challenge: ProofChallenge): Future[?!Groth16Proof] {.
3438
gcsafe, async: (raises: [CancelledError])

codex/sales/slotqueue.nim

Lines changed: 27 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ type
3030
duration: uint64
3131
pricePerBytePerSecond: UInt256
3232
collateral: UInt256 # Collateral computed
33-
expiry: uint64
33+
expiry: ?uint64
3434
seen: bool
3535

3636
# don't need to -1 to prevent overflow when adding 1 (to always allow push)
@@ -89,8 +89,9 @@ proc `<`*(a, b: SlotQueueItem): bool =
8989
scoreA.addIf(a.collateral < b.collateral, 2)
9090
scoreB.addIf(a.collateral > b.collateral, 2)
9191

92-
scoreA.addIf(a.expiry > b.expiry, 1)
93-
scoreB.addIf(a.expiry < b.expiry, 1)
92+
if expiryA =? a.expiry and expiryB =? b.expiry:
93+
scoreA.addIf(expiryA > expiryB, 1)
94+
scoreB.addIf(expiryA < expiryB, 1)
9495

9596
return scoreA > scoreB
9697

@@ -124,7 +125,7 @@ proc init*(
124125
requestId: RequestId,
125126
slotIndex: uint16,
126127
ask: StorageAsk,
127-
expiry: uint64,
128+
expiry: ?uint64,
128129
collateral: UInt256,
129130
seen = false,
130131
): SlotQueueItem =
@@ -139,6 +140,17 @@ proc init*(
139140
seen: seen,
140141
)
141142

143+
proc init*(
144+
_: type SlotQueueItem,
145+
requestId: RequestId,
146+
slotIndex: uint16,
147+
ask: StorageAsk,
148+
expiry: uint64,
149+
collateral: UInt256,
150+
seen = false,
151+
): SlotQueueItem =
152+
SlotQueueItem.init(requestId, slotIndex, ask, some expiry, collateral, seen)
153+
142154
proc init*(
143155
_: type SlotQueueItem,
144156
request: StorageRequest,
@@ -151,7 +163,7 @@ proc init*(
151163
_: type SlotQueueItem,
152164
requestId: RequestId,
153165
ask: StorageAsk,
154-
expiry: uint64,
166+
expiry: ?uint64,
155167
collateral: UInt256,
156168
): seq[SlotQueueItem] {.raises: [SlotsOutOfRangeError].} =
157169
if not ask.slots.inRange:
@@ -167,10 +179,19 @@ proc init*(
167179
Rng.instance.shuffle(items)
168180
return items
169181

182+
proc init*(
183+
_: type SlotQueueItem,
184+
requestId: RequestId,
185+
ask: StorageAsk,
186+
expiry: uint64,
187+
collateral: UInt256,
188+
): seq[SlotQueueItem] {.raises: [SlotsOutOfRangeError].} =
189+
SlotQueueItem.init(requestId, ask, some expiry, collateral)
190+
170191
proc init*(
171192
_: type SlotQueueItem, request: StorageRequest, collateral: UInt256
172193
): seq[SlotQueueItem] =
173-
return SlotQueueItem.init(request.id, request.ask, request.expiry, collateral)
194+
return SlotQueueItem.init(request.id, request.ask, uint64.none, collateral)
174195

175196
proc inRange*(val: SomeUnsignedInt): bool =
176197
val.uint16 in SlotQueueSize.low .. SlotQueueSize.high

codex/sales/states/downloading.nim

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ method run*(
3838
let agent = SalesAgent(machine)
3939
let data = agent.data
4040
let context = agent.context
41+
let market = context.market
4142
let reservations = context.reservations
4243

4344
without onStore =? context.onStore:
@@ -69,11 +70,21 @@ method run*(
6970
return await reservations.release(reservation.id, reservation.availabilityId, bytes)
7071

7172
try:
72-
let slotId = slotId(request.id, data.slotIndex)
73-
let isRepairing = (await context.market.slotState(slotId)) == SlotState.Repair
73+
let requestId = request.id
74+
let slotId = slotId(requestId, data.slotIndex)
75+
let requestState = await market.requestState(requestId)
76+
let isRepairing = (await market.slotState(slotId)) == SlotState.Repair
77+
78+
trace "Retrieving expiry"
79+
var expiry: SecondsSince1970
80+
if state =? requestState and state == RequestState.Started:
81+
expiry = await market.getRequestEnd(requestId)
82+
else:
83+
expiry = await market.requestExpiresAt(requestId)
7484

7585
trace "Starting download"
76-
if err =? (await onStore(request, data.slotIndex, onBlocks, isRepairing)).errorOption:
86+
if err =?
87+
(await onStore(request, expiry, data.slotIndex, onBlocks, isRepairing)).errorOption:
7788
return some State(SaleErrored(error: err, reprocessSlot: false))
7889

7990
trace "Download complete"

tests/codex/helpers/mockmarket.nim

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ from pkg/ethers import BlockTag
1414
import codex/clock
1515

1616
import ../examples
17+
import ./mockclock
1718

1819
export market
1920
export tables
@@ -51,7 +52,7 @@ type
5152
errorOnFillSlot*: ?(ref MarketError)
5253
errorOnFreeSlot*: ?(ref MarketError)
5354
errorOnGetHost*: ?(ref MarketError)
54-
clock: ?Clock
55+
clock: Clock
5556

5657
Fulfillment* = object
5758
requestId*: RequestId
@@ -63,7 +64,7 @@ type
6364
host*: Address
6465
slotIndex*: uint64
6566
proof*: Groth16Proof
66-
timestamp: ?SecondsSince1970
67+
timestamp: SecondsSince1970
6768
collateral*: UInt256
6869

6970
Subscriptions = object
@@ -119,7 +120,7 @@ proc hash*(address: Address): Hash =
119120
proc hash*(requestId: RequestId): Hash =
120121
hash(requestId.toArray)
121122

122-
proc new*(_: type MockMarket, clock: ?Clock = Clock.none): MockMarket =
123+
proc new*(_: type MockMarket, clock: Clock = MockClock.new()): MockMarket =
123124
## Create a new mocked Market instance
124125
##
125126
let config = MarketplaceConfig(
@@ -181,10 +182,15 @@ method getPointer*(market: MockMarket, slotId: SlotId): Future[uint8] {.async.}
181182
method requestStorage*(
182183
market: MockMarket, request: StorageRequest
183184
) {.async: (raises: [CancelledError, MarketError]).} =
185+
let now = market.clock.now()
186+
let requestExpiresAt = now + request.expiry.toSecondsSince1970
187+
let requestEndsAt = now + request.ask.duration.toSecondsSince1970
184188
market.requested.add(request)
189+
market.requestExpiry[request.id] = requestExpiresAt
190+
market.requestEnds[request.id] = requestEndsAt
185191
var subscriptions = market.subscriptions.onRequest
186192
for subscription in subscriptions:
187-
subscription.callback(request.id, request.ask, request.expiry)
193+
subscription.callback(request.id, request.ask, requestExpiresAt.uint64)
188194

189195
method myRequests*(market: MockMarket): Future[seq[RequestId]] {.async.} =
190196
return market.activeRequests[market.signer]
@@ -308,7 +314,7 @@ proc fillSlot*(
308314
slotIndex: slotIndex,
309315
proof: proof,
310316
host: host,
311-
timestamp: market.clock .? now,
317+
timestamp: market.clock.now,
312318
collateral: collateral,
313319
)
314320
market.filled.add(slot)
@@ -541,15 +547,23 @@ method queryPastStorageRequestedEvents*(
541547
): Future[seq[StorageRequested]] {.async.} =
542548
return market.requested.map(
543549
request =>
544-
StorageRequested(requestId: request.id, ask: request.ask, expiry: request.expiry)
550+
StorageRequested(
551+
requestId: request.id,
552+
ask: request.ask,
553+
expiry: market.requestExpiry[request.id].uint64,
554+
)
545555
)
546556

547557
method queryPastStorageRequestedEvents*(
548558
market: MockMarket, blocksAgo: int
549559
): Future[seq[StorageRequested]] {.async.} =
550560
return market.requested.map(
551561
request =>
552-
StorageRequested(requestId: request.id, ask: request.ask, expiry: request.expiry)
562+
StorageRequested(
563+
requestId: request.id,
564+
ask: request.ask,
565+
expiry: market.requestExpiry[request.id].uint64,
566+
)
553567
)
554568

555569
method queryPastSlotFilledEvents*(
@@ -571,10 +585,7 @@ method queryPastSlotFilledEvents*(
571585
): Future[seq[SlotFilled]] {.async.} =
572586
let filtered = market.filled.filter(
573587
proc(slot: MockSlot): bool =
574-
if timestamp =? slot.timestamp:
575-
return timestamp >= fromTime
576-
else:
577-
true
588+
return slot.timestamp >= fromTime
578589
)
579590
return filtered.map(
580591
slot => SlotFilled(requestId: slot.requestId, slotIndex: slot.slotIndex)

tests/codex/node/testcontracts.nim

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,7 @@ asyncchecksuite "Test Node - Host contracts":
116116
let onStore = !sales.onStore
117117
var request = StorageRequest.example
118118
request.content.cid = verifiableBlock.cid
119-
request.expiry =
120-
(getTime() + DefaultBlockTtl.toTimesDuration + 1.hours).toUnix.uint64
119+
let expiry = (getTime() + DefaultBlockTtl.toTimesDuration + 1.hours).toUnix
121120
var fetchedBytes: uint = 0
122121

123122
let onBlocks = proc(
@@ -127,7 +126,7 @@ asyncchecksuite "Test Node - Host contracts":
127126
fetchedBytes += blk.data.len.uint
128127
return success()
129128

130-
(await onStore(request, 1.uint64, onBlocks, isRepairing = false)).tryGet()
129+
(await onStore(request, expiry, 1.uint64, onBlocks, isRepairing = false)).tryGet()
131130
check fetchedBytes == 12 * DefaultBlockSize.uint
132131

133132
let indexer = verifiable.protectedStrategy.init(
@@ -141,4 +140,4 @@ asyncchecksuite "Test Node - Host contracts":
141140
bytes = (await localStoreMetaDs.get(key)).tryGet
142141
blkMd = BlockMetadata.decode(bytes).tryGet
143142

144-
check blkMd.expiry == request.expiry.toSecondsSince1970
143+
check blkMd.expiry == expiry

0 commit comments

Comments
 (0)