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