mirror of
https://github.com/codex-storage/codex-contracts-eth.git
synced 2025-02-13 11:56:46 +00:00
set proof end when storage requested
1. set proof end to now + duration when storage is requested 2. set proof end to past when contract is failed 3. add back proof end mappings
This commit is contained in:
parent
fd74268a8a
commit
bac2675bb2
@ -37,6 +37,11 @@ contract Marketplace is Collateral, Proofs {
|
||||
require(requests[id].client == address(0), "Request already exists");
|
||||
|
||||
requests[id] = request;
|
||||
RequestContext storage context = _context(id);
|
||||
// set contract end time to `duration` from now (time request was created)
|
||||
context.endsAt = block.timestamp + request.ask.duration;
|
||||
_setProofEnd(id, context.endsAt);
|
||||
|
||||
|
||||
_createLock(id, request.expiry);
|
||||
|
||||
@ -63,14 +68,13 @@ contract Marketplace is Collateral, Proofs {
|
||||
require(balanceOf(msg.sender) >= collateral, "Insufficient collateral");
|
||||
_lock(msg.sender, requestId);
|
||||
|
||||
_expectProofs(slotId, request.ask.proofProbability, request.ask.duration);
|
||||
_expectProofs(slotId, requestId, request.ask.proofProbability);
|
||||
_submitProof(slotId, proof);
|
||||
|
||||
slot.host = msg.sender;
|
||||
slot.requestId = requestId;
|
||||
RequestContext storage context = _context(requestId);
|
||||
context.slotsFilled += 1;
|
||||
context.endsAt = block.timestamp + request.ask.duration;
|
||||
emit SlotFilled(requestId, slotIndex, slotId);
|
||||
if (context.slotsFilled == request.ask.slots) {
|
||||
context.state = RequestState.Started;
|
||||
@ -105,6 +109,7 @@ contract Marketplace is Collateral, Proofs {
|
||||
context.state == RequestState.Started) {
|
||||
|
||||
context.state = RequestState.Failed;
|
||||
_setProofEnd(requestId, block.timestamp - 1);
|
||||
context.endsAt = block.timestamp - 1;
|
||||
emit RequestFailed(requestId);
|
||||
|
||||
@ -233,15 +238,11 @@ contract Marketplace is Collateral, Proofs {
|
||||
|
||||
function proofEnd(bytes32 slotId) public view returns (uint256) {
|
||||
Slot memory slot = _slot(slotId);
|
||||
uint256 end = _end(slotId);
|
||||
RequestContext storage context = _context(slot.requestId);
|
||||
uint256 end = _end(slot.requestId);
|
||||
if (_slotAcceptsProofs(slotId)) {
|
||||
return end;
|
||||
} else {
|
||||
// Calculate the earliest ending between a slot and a request.
|
||||
// Request endings are set, for eg, when a request fails.
|
||||
uint256 earliestEnd = Math.min(end, context.endsAt);
|
||||
return Math.min(earliestEnd, block.timestamp - 1);
|
||||
return Math.min(end, block.timestamp - 1);
|
||||
}
|
||||
}
|
||||
|
||||
@ -276,7 +277,6 @@ contract Marketplace is Collateral, Proofs {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @notice returns true when the request is accepting proof submissions from hosts occupying slots.
|
||||
/// @dev Request state must be new or started, and must not be cancelled, finished, or failed.
|
||||
/// @param requestId id of the request for which to obtain state info
|
||||
|
@ -20,6 +20,7 @@ contract Proofs {
|
||||
mapping(bytes32 => bool) private ids;
|
||||
mapping(bytes32 => uint256) private starts;
|
||||
mapping(bytes32 => uint256) private ends;
|
||||
mapping(bytes32 => bytes32) private idEnds;
|
||||
mapping(bytes32 => uint256) private probabilities;
|
||||
mapping(bytes32 => uint256) private markers;
|
||||
mapping(bytes32 => uint256) private missed;
|
||||
@ -34,10 +35,21 @@ contract Proofs {
|
||||
return timeout;
|
||||
}
|
||||
|
||||
function _end(bytes32 id) internal view returns (uint256) {
|
||||
uint256 end = ends[id];
|
||||
function _end(bytes32 endId) internal view returns (uint256) {
|
||||
uint256 end = ends[endId];
|
||||
require(end > 0, "Proof ending doesn't exist");
|
||||
return ends[id];
|
||||
return ends[endId];
|
||||
}
|
||||
|
||||
function _endId(bytes32 id) internal view returns (bytes32) {
|
||||
bytes32 endId = idEnds[id];
|
||||
require(endId > 0, "endId for given id doesn't exist");
|
||||
return endId;
|
||||
}
|
||||
|
||||
function _endFromId(bytes32 id) internal view returns (uint256) {
|
||||
bytes32 endId = _endId(id);
|
||||
return _end(endId);
|
||||
}
|
||||
|
||||
function _missed(bytes32 id) internal view returns (uint256) {
|
||||
@ -55,19 +67,19 @@ contract Proofs {
|
||||
/// @notice Informs the contract that proofs should be expected for id
|
||||
/// @dev Requires that the id is not already in use
|
||||
/// @param id identifies the proof expectation, typically a slot id
|
||||
/// @param endId Identifies the id of the proof expectation ending. Typically a request id. Different from id because the proof ending is shared amongst many ids.
|
||||
/// @param probability The probability that a proof should be expected
|
||||
/// @param duration Duration, from now, for which proofs should be expected
|
||||
function _expectProofs(
|
||||
bytes32 id, // typically slot id
|
||||
uint256 probability,
|
||||
uint256 duration
|
||||
bytes32 endId, // typically request id, used so that the ending is global for all slots
|
||||
uint256 probability
|
||||
) internal {
|
||||
require(!ids[id], "Proof id already in use");
|
||||
ids[id] = true;
|
||||
starts[id] = block.timestamp;
|
||||
ends[id] = block.timestamp + duration;
|
||||
probabilities[id] = probability;
|
||||
markers[id] = uint256(blockhash(block.number - 1)) % period;
|
||||
idEnds[id] = endId;
|
||||
}
|
||||
|
||||
function _unexpectProofs(
|
||||
@ -119,7 +131,7 @@ contract Proofs {
|
||||
if (proofPeriod <= periodOf(starts[id])) {
|
||||
return (false, 0);
|
||||
}
|
||||
uint256 end = _end(id);
|
||||
uint256 end = _endFromId(id);
|
||||
if (proofPeriod >= periodOf(end)) {
|
||||
return (false, 0);
|
||||
}
|
||||
@ -169,5 +181,16 @@ contract Proofs {
|
||||
missed[id] += 1;
|
||||
}
|
||||
|
||||
/// @notice Sets the proof end time
|
||||
/// @dev Can only be set once
|
||||
/// @param endId the endId of the proofs to extend (typically a request id).
|
||||
/// @param ending the new end time (in seconds)
|
||||
function _setProofEnd(bytes32 endId, uint256 ending) internal {
|
||||
// TODO: create type aliases for id and endId so that _end() can return
|
||||
// EndId storage and we don't need to replicate the below require here
|
||||
require (ends[endId] == 0 || ending < block.timestamp, "End exists or must be past");
|
||||
ends[endId] = ending;
|
||||
}
|
||||
|
||||
event ProofSubmitted(bytes32 id, bytes proof);
|
||||
}
|
||||
|
@ -34,10 +34,10 @@ contract TestProofs is Proofs {
|
||||
|
||||
function expectProofs(
|
||||
bytes32 id,
|
||||
uint256 _probability,
|
||||
uint256 _duration
|
||||
bytes32 endId,
|
||||
uint256 _probability
|
||||
) public {
|
||||
_expectProofs(id, _probability, _duration);
|
||||
_expectProofs(id, endId, _probability);
|
||||
}
|
||||
|
||||
function unexpectProofs(bytes32 id) public {
|
||||
@ -67,4 +67,8 @@ contract TestProofs is Proofs {
|
||||
function markProofAsMissing(bytes32 id, uint256 _period) public {
|
||||
_markProofAsMissing(id, _period);
|
||||
}
|
||||
|
||||
function setProofEnd(bytes32 id, uint256 ending) public {
|
||||
_setProofEnd(id, ending);
|
||||
}
|
||||
}
|
||||
|
@ -212,10 +212,12 @@ describe("Marketplace", function () {
|
||||
})
|
||||
|
||||
describe("proof end", function () {
|
||||
var requestTime
|
||||
beforeEach(async function () {
|
||||
switchAccount(client)
|
||||
await token.approve(marketplace.address, price(request))
|
||||
await marketplace.requestStorage(request)
|
||||
requestTime = await currentTime()
|
||||
switchAccount(host)
|
||||
await token.approve(marketplace.address, collateral)
|
||||
await marketplace.deposit(collateral)
|
||||
@ -236,11 +238,11 @@ describe("Marketplace", function () {
|
||||
}
|
||||
})
|
||||
|
||||
it("sets proof end time to the request duration once filled", async function () {
|
||||
it("sets the proof end time to now + duration", async function () {
|
||||
await marketplace.fillSlot(slot.request, slot.index, proof)
|
||||
await expect(await marketplace.proofEnd(slotId(slot))).to.be.eq(
|
||||
(await currentTime()) + request.ask.duration
|
||||
)
|
||||
await expect(
|
||||
(await marketplace.proofEnd(slotId(slot))).toNumber()
|
||||
).to.be.closeTo(requestTime + request.ask.duration, 1)
|
||||
})
|
||||
|
||||
it("sets proof end time to the past once failed", async function () {
|
||||
@ -258,15 +260,14 @@ describe("Marketplace", function () {
|
||||
await expect(await marketplace.proofEnd(slotId(slot))).to.be.eq(now - 1)
|
||||
})
|
||||
|
||||
it("sets proof end time to the past once finished", async function () {
|
||||
it("checks that proof end time is in the past once finished", async function () {
|
||||
const lastSlot = await waitUntilStarted(marketplace, request, slot, proof)
|
||||
await waitUntilFinished(marketplace, lastSlot) // sets proofEnd to block.timestamp - 1
|
||||
await waitUntilFinished(marketplace, lastSlot)
|
||||
const now = await currentTime()
|
||||
// the proof end time is set to block.timestamp - 1 when the contract is
|
||||
// finished. in the process of calling currentTime and proofEnd,
|
||||
// in the process of calling currentTime and proofEnd,
|
||||
// block.timestamp has advanced by 1, so the expected proof end time will
|
||||
// be block.timestamp - 2.
|
||||
await expect(await marketplace.proofEnd(slotId(slot))).to.be.eq(now - 2)
|
||||
// be block.timestamp - 1.
|
||||
await expect(await marketplace.proofEnd(slotId(slot))).to.be.eq(now - 1)
|
||||
})
|
||||
})
|
||||
|
||||
|
@ -14,6 +14,7 @@ const { periodic, hours, minutes } = require("./time")
|
||||
|
||||
describe("Proofs", function () {
|
||||
const id = hexlify(randomBytes(32))
|
||||
const endId = hexlify(randomBytes(32))
|
||||
const period = 30 * 60
|
||||
const timeout = 5
|
||||
const downtime = 64
|
||||
@ -34,21 +35,20 @@ describe("Proofs", function () {
|
||||
await revert()
|
||||
})
|
||||
|
||||
it("calculates an end time based on duration", async function () {
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
let end = (await currentTime()) + duration
|
||||
expect((await proofs.end(id)).toNumber()).to.be.closeTo(end, 1)
|
||||
describe("general", function () {
|
||||
beforeEach(async function () {
|
||||
await proofs.setProofEnd(endId, (await currentTime()) + duration)
|
||||
})
|
||||
|
||||
it("does not allow ids to be reused", async function () {
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
await expect(
|
||||
proofs.expectProofs(id, probability, duration)
|
||||
proofs.expectProofs(id, endId, probability)
|
||||
).to.be.revertedWith("Proof id already in use")
|
||||
})
|
||||
|
||||
it("requires proofs with an agreed upon probability", async function () {
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
let amount = 0
|
||||
for (let i = 0; i < 100; i++) {
|
||||
if (await proofs.isProofRequired(id)) {
|
||||
@ -63,7 +63,7 @@ describe("Proofs", function () {
|
||||
it("requires no proofs in the start period", async function () {
|
||||
const startPeriod = Math.floor((await currentTime()) / period)
|
||||
const probability = 1
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
while (Math.floor((await currentTime()) / period) == startPeriod) {
|
||||
expect(await proofs.isProofRequired(id)).to.be.false
|
||||
await advanceTime(Math.floor(period / 10))
|
||||
@ -72,14 +72,14 @@ describe("Proofs", function () {
|
||||
|
||||
it("requires no proofs in the end period", async function () {
|
||||
const probability = 1
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
await advanceTime(duration)
|
||||
expect(await proofs.isProofRequired(id)).to.be.false
|
||||
})
|
||||
|
||||
it("requires no proofs after the end time", async function () {
|
||||
const probability = 1
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
await advanceTime(duration + timeout)
|
||||
expect(await proofs.isProofRequired(id)).to.be.false
|
||||
})
|
||||
@ -89,7 +89,7 @@ describe("Proofs", function () {
|
||||
let id2 = hexlify(randomBytes(32))
|
||||
let id3 = hexlify(randomBytes(32))
|
||||
for (let id of [id1, id2, id3]) {
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
}
|
||||
let req1, req2, req3
|
||||
while (req1 === req2 && req2 === req3) {
|
||||
@ -109,6 +109,7 @@ describe("Proofs", function () {
|
||||
expect(current).to.equal((previous + 1) % 256)
|
||||
}
|
||||
})
|
||||
})
|
||||
|
||||
describe("when proof requirement is upcoming", function () {
|
||||
async function waitUntilProofWillBeRequired() {
|
||||
@ -118,7 +119,8 @@ describe("Proofs", function () {
|
||||
}
|
||||
|
||||
beforeEach(async function () {
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.setProofEnd(endId, (await currentTime()) + duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
await advanceTimeTo(periodEnd(periodOf(await currentTime())))
|
||||
await waitUntilProofWillBeRequired()
|
||||
})
|
||||
@ -151,7 +153,8 @@ describe("Proofs", function () {
|
||||
const proof = hexlify(randomBytes(42))
|
||||
|
||||
beforeEach(async function () {
|
||||
await proofs.expectProofs(id, probability, duration)
|
||||
await proofs.setProofEnd(endId, (await currentTime()) + duration)
|
||||
await proofs.expectProofs(id, endId, probability)
|
||||
})
|
||||
|
||||
async function waitUntilProofIsRequired(id) {
|
||||
@ -270,4 +273,35 @@ describe("Proofs", function () {
|
||||
await expect(await proofs.isProofRequired(id)).to.be.false
|
||||
})
|
||||
})
|
||||
|
||||
describe("set proof end", function () {
|
||||
const proof = hexlify(randomBytes(42))
|
||||
|
||||
it("fails to get proof end when proof ending doesn't exist", async function () {
|
||||
await expect(proofs.end(endId)).to.be.revertedWith(
|
||||
"Proof ending doesn't exist"
|
||||
)
|
||||
})
|
||||
|
||||
it("sets proof end when proof ending doesn't already exist", async function () {
|
||||
let ending = (await currentTime()) + duration
|
||||
await expect(proofs.setProofEnd(endId, ending)).not.to.be.reverted
|
||||
await expect(await proofs.end(endId)).to.equal(ending)
|
||||
})
|
||||
|
||||
it("sets proof end when proof ending exists and ending set to past", async function () {
|
||||
// let ending = (await currentTime()) + duration
|
||||
// await proofs.setProofEnd(endId, ending)
|
||||
let past = (await currentTime()) - 1
|
||||
await expect(proofs.setProofEnd(endId, past)).not.to.be.reverted
|
||||
})
|
||||
|
||||
it("fails when proof ending already exists and ending set to future", async function () {
|
||||
let ending = (await currentTime()) + duration
|
||||
await proofs.setProofEnd(endId, ending)
|
||||
await expect(proofs.setProofEnd(endId, ending)).to.be.revertedWith(
|
||||
"End exists or must be past"
|
||||
)
|
||||
})
|
||||
})
|
||||
})
|
||||
|
Loading…
x
Reference in New Issue
Block a user