Add challenge to prove callback (#649)
* Sets up passing proof challenge to onProve callback * Implements tests for proof challenge * Removes unused import
This commit is contained in:
parent
3907ca4095
commit
a9f8090bb4
|
@ -143,6 +143,9 @@ method willProofBeRequired*(market: OnChainMarket,
|
|||
return false
|
||||
raise e
|
||||
|
||||
method getChallenge*(market: OnChainMarket, id: SlotId): Future[ProofChallenge] {.async.} =
|
||||
return await market.contract.getChallenge(id)
|
||||
|
||||
method submitProof*(market: OnChainMarket,
|
||||
id: SlotId,
|
||||
proof: seq[byte]) {.async.} =
|
||||
|
|
|
@ -28,6 +28,7 @@ type
|
|||
requestId*: RequestId
|
||||
ask*: StorageAsk
|
||||
expiry*: UInt256
|
||||
ProofChallenge* = array[32, byte]
|
||||
|
||||
method getSigner*(market: Market): Future[Address] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
@ -103,6 +104,9 @@ method willProofBeRequired*(market: Market,
|
|||
id: SlotId): Future[bool] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method getChallenge*(market: Market, id: SlotId): Future[ProofChallenge] {.base, async.} =
|
||||
raiseAssert("not implemented")
|
||||
|
||||
method submitProof*(market: Market,
|
||||
id: SlotId,
|
||||
proof: seq[byte]) {.base, async.} =
|
||||
|
|
|
@ -458,7 +458,7 @@ proc start*(node: CodexNodeRef) {.async.} =
|
|||
# TODO: remove data from local storage
|
||||
discard
|
||||
|
||||
hostContracts.sales.onProve = proc(slot: Slot): Future[seq[byte]] {.async.} =
|
||||
hostContracts.sales.onProve = proc(slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
# TODO: generate proof
|
||||
return @[42'u8]
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ type
|
|||
OnStore* = proc(request: StorageRequest,
|
||||
slot: UInt256,
|
||||
onBatch: BatchProc): Future[?!void] {.gcsafe, upraises: [].}
|
||||
OnProve* = proc(slot: Slot): Future[seq[byte]] {.gcsafe, upraises: [].}
|
||||
OnProve* = proc(slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.gcsafe, upraises: [].}
|
||||
OnExpiryUpdate* = proc(rootCid: string, expiry: SecondsSince1970): Future[?!void] {.gcsafe, upraises: [].}
|
||||
OnClear* = proc(request: StorageRequest,
|
||||
slotIndex: UInt256) {.gcsafe, upraises: [].}
|
||||
|
|
|
@ -31,7 +31,10 @@ method run*(state: SaleInitialProving, machine: Machine): Future[?State] {.async
|
|||
raiseAssert "onProve callback not set"
|
||||
|
||||
debug "Generating initial proof", requestId = $data.requestId
|
||||
let proof = await onProve(Slot(request: request, slotIndex: data.slotIndex))
|
||||
let
|
||||
slot = Slot(request: request, slotIndex: data.slotIndex)
|
||||
challenge = await context.market.getChallenge(slot.id)
|
||||
proof = await onProve(slot, challenge)
|
||||
debug "Finished proof calculation", requestId = $data.requestId
|
||||
|
||||
return some State(SaleFilling(proof: proof))
|
||||
|
|
|
@ -21,12 +21,13 @@ type
|
|||
method prove*(
|
||||
state: SaleProving,
|
||||
slot: Slot,
|
||||
challenge: ProofChallenge,
|
||||
onProve: OnProve,
|
||||
market: Market,
|
||||
currentPeriod: Period
|
||||
) {.base, async.} =
|
||||
try:
|
||||
let proof = await onProve(slot)
|
||||
let proof = await onProve(slot, challenge)
|
||||
debug "Submitting proof", currentPeriod = currentPeriod, slotId = $slot.id
|
||||
await market.submitProof(slot.id, proof)
|
||||
except CatchableError as e:
|
||||
|
@ -71,8 +72,9 @@ proc proveLoop(
|
|||
debug "Proving for new period", period = currentPeriod
|
||||
|
||||
if (await market.isProofRequired(slotId)) or (await market.willProofBeRequired(slotId)):
|
||||
debug "Proof is required", period = currentPeriod
|
||||
await state.prove(slot, onProve, market, currentPeriod)
|
||||
let challenge = await market.getChallenge(slotId)
|
||||
debug "Proof is required", period = currentPeriod, challenge = challenge
|
||||
await state.prove(slot, challenge, onProve, market, currentPeriod)
|
||||
|
||||
await waitUntilPeriod(currentPeriod + 1)
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ when codex_enable_proof_failures:
|
|||
proc onSubmitProofError(error: ref CatchableError, period: UInt256, slotId: SlotId) =
|
||||
error "Submitting invalid proof failed", period = period, slotId = $slotId, msg = error.msg
|
||||
|
||||
method prove*(state: SaleProvingSimulated, slot: Slot, onProve: OnProve, market: Market, currentPeriod: Period) {.async.} =
|
||||
method prove*(state: SaleProvingSimulated, slot: Slot, challenge: ProofChallenge, onProve: OnProve, market: Market, currentPeriod: Period) {.async.} =
|
||||
trace "Processing proving in simulated mode"
|
||||
state.proofCount += 1
|
||||
if state.failEveryNProofs > 0 and
|
||||
|
@ -38,4 +38,4 @@ when codex_enable_proof_failures:
|
|||
except CatchableError as e:
|
||||
onSubmitProofError(e, currentPeriod, slot.id)
|
||||
else:
|
||||
await procCall SaleProving(state).prove(slot, onProve, market, currentPeriod)
|
||||
await procCall SaleProving(state).prove(slot, challenge, onProve, market, currentPeriod)
|
||||
|
|
|
@ -71,4 +71,3 @@ proc example*(_: type Reservation): Reservation =
|
|||
size = uint16.example.u256,
|
||||
slotId = SlotId.example
|
||||
)
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ type
|
|||
withdrawn*: seq[RequestId]
|
||||
proofsRequired: HashSet[SlotId]
|
||||
proofsToBeRequired: HashSet[SlotId]
|
||||
proofChallenge*: ProofChallenge
|
||||
proofEnds: Table[SlotId, UInt256]
|
||||
signer: Address
|
||||
subscriptions: Subscriptions
|
||||
|
@ -235,7 +236,6 @@ method freeSlot*(market: MockMarket, slotId: SlotId) {.async.} =
|
|||
break
|
||||
market.slotState[slotId] = SlotState.Free
|
||||
|
||||
|
||||
method withdrawFunds*(market: MockMarket,
|
||||
requestId: RequestId) {.async.} =
|
||||
market.withdrawn.add(requestId)
|
||||
|
@ -261,6 +261,9 @@ method willProofBeRequired*(mock: MockMarket,
|
|||
id: SlotId): Future[bool] {.async.} =
|
||||
return mock.proofsToBeRequired.contains(id)
|
||||
|
||||
method getChallenge*(mock: MockMarket, id: SlotId): Future[ProofChallenge] {.async.} =
|
||||
return mock.proofChallenge
|
||||
|
||||
proc setProofEnd*(mock: MockMarket, id: SlotId, proofEnd: UInt256) =
|
||||
mock.proofEnds[id] = proofEnd
|
||||
|
||||
|
|
|
@ -8,22 +8,29 @@ import pkg/codex/sales/states/failed
|
|||
import pkg/codex/sales/states/filling
|
||||
import pkg/codex/sales/salesagent
|
||||
import pkg/codex/sales/salescontext
|
||||
import pkg/codex/market
|
||||
import ../../examples
|
||||
import ../../helpers
|
||||
import ../../helpers/mockmarket
|
||||
|
||||
asyncchecksuite "sales state 'initialproving'":
|
||||
|
||||
let proof = exampleProof()
|
||||
let request = StorageRequest.example
|
||||
let slotIndex = (request.ask.slots div 2).u256
|
||||
let market = MockMarket.new()
|
||||
|
||||
var state: SaleInitialProving
|
||||
var agent: SalesAgent
|
||||
var receivedChallenge: ProofChallenge
|
||||
|
||||
setup:
|
||||
let onProve = proc (slot: Slot): Future[seq[byte]] {.async.} =
|
||||
let onProve = proc (slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
receivedChallenge = challenge
|
||||
return proof
|
||||
let context = SalesContext(onProve: onProve.some)
|
||||
let context = SalesContext(
|
||||
onProve: onProve.some,
|
||||
market: market
|
||||
)
|
||||
agent = newSalesAgent(context,
|
||||
request.id,
|
||||
slotIndex,
|
||||
|
@ -42,3 +49,10 @@ asyncchecksuite "sales state 'initialproving'":
|
|||
let next = await state.run(agent)
|
||||
check !next of SaleFilling
|
||||
check SaleFilling(!next).proof == proof
|
||||
|
||||
test "onProve callback provides proof challenge":
|
||||
market.proofChallenge = ProofChallenge.example
|
||||
|
||||
let future = state.run(agent)
|
||||
|
||||
check receivedChallenge == market.proofChallenge
|
||||
|
|
|
@ -23,11 +23,13 @@ asyncchecksuite "sales state 'proving'":
|
|||
var clock: MockClock
|
||||
var agent: SalesAgent
|
||||
var state: SaleProving
|
||||
var receivedChallenge: ProofChallenge
|
||||
|
||||
setup:
|
||||
clock = MockClock.new()
|
||||
market = MockMarket.new()
|
||||
let onProve = proc (slot: Slot): Future[seq[byte]] {.async.} =
|
||||
let onProve = proc (slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
receivedChallenge = challenge
|
||||
return proof
|
||||
let context = SalesContext(market: market, clock: clock, onProve: onProve.some)
|
||||
agent = newSalesAgent(context,
|
||||
|
@ -80,3 +82,11 @@ asyncchecksuite "sales state 'proving'":
|
|||
check eventually future.finished
|
||||
check !(future.read()) of SalePayout
|
||||
|
||||
test "onProve callback provides proof challenge":
|
||||
market.proofChallenge = ProofChallenge.example
|
||||
market.slotState[slot.id] = SlotState.Filled
|
||||
market.setProofRequired(slot.id, true)
|
||||
|
||||
let future = state.run(agent)
|
||||
|
||||
check receivedChallenge == market.proofChallenge
|
||||
|
|
|
@ -44,7 +44,7 @@ asyncchecksuite "sales state 'simulated-proving'":
|
|||
market.setProofRequired(slot.id, true)
|
||||
subscription = await market.subscribeProofSubmission(onProofSubmission)
|
||||
|
||||
let onProve = proc (slot: Slot): Future[seq[byte]] {.async.} =
|
||||
let onProve = proc (slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
return proof
|
||||
let context = SalesContext(market: market, clock: clock, onProve: onProve.some)
|
||||
agent = newSalesAgent(context,
|
||||
|
|
|
@ -64,7 +64,7 @@ asyncchecksuite "Sales - start":
|
|||
return success()
|
||||
|
||||
queue = sales.context.slotQueue
|
||||
sales.onProve = proc(slot: Slot): Future[seq[byte]] {.async.} =
|
||||
sales.onProve = proc(slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
return proof
|
||||
itemsProcessed = @[]
|
||||
request.expiry = (clock.now() + 42).u256
|
||||
|
@ -166,7 +166,7 @@ asyncchecksuite "Sales":
|
|||
return success()
|
||||
|
||||
queue = sales.context.slotQueue
|
||||
sales.onProve = proc(slot: Slot): Future[seq[byte]] {.async.} =
|
||||
sales.onProve = proc(slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
return proof
|
||||
await sales.start()
|
||||
request.expiry = (clock.now() + 42).u256
|
||||
|
@ -369,7 +369,7 @@ asyncchecksuite "Sales":
|
|||
|
||||
test "handles errors during state run":
|
||||
var saleFailed = false
|
||||
sales.onProve = proc(slot: Slot): Future[seq[byte]] {.async.} =
|
||||
sales.onProve = proc(slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
# raise exception so machine.onError is called
|
||||
raise newException(ValueError, "some error")
|
||||
|
||||
|
@ -394,7 +394,7 @@ asyncchecksuite "Sales":
|
|||
test "generates proof of storage":
|
||||
var provingRequest: StorageRequest
|
||||
var provingSlot: UInt256
|
||||
sales.onProve = proc(slot: Slot): Future[seq[byte]] {.async.} =
|
||||
sales.onProve = proc(slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
provingRequest = slot.request
|
||||
provingSlot = slot.slotIndex
|
||||
createAvailability()
|
||||
|
@ -426,7 +426,7 @@ asyncchecksuite "Sales":
|
|||
test "calls onClear when storage becomes available again":
|
||||
# fail the proof intentionally to trigger `agent.finish(success=false)`,
|
||||
# which then calls the onClear callback
|
||||
sales.onProve = proc(slot: Slot): Future[seq[byte]] {.async.} =
|
||||
sales.onProve = proc(slot: Slot, challenge: ProofChallenge): Future[seq[byte]] {.async.} =
|
||||
raise newException(IOError, "proof failed")
|
||||
var clearedRequest: StorageRequest
|
||||
var clearedSlotIndex: UInt256
|
||||
|
|
Loading…
Reference in New Issue