Add end time to proofs based on contract duration

This commit is contained in:
Mark Spanbroek 2021-11-03 13:24:50 +01:00
parent 3326c4fe74
commit 2784800c3e
4 changed files with 45 additions and 17 deletions

View File

@ -6,6 +6,7 @@ contract Proofs {
mapping(bytes32=>bool) private ids; mapping(bytes32=>bool) private ids;
mapping(bytes32=>uint) private periods; mapping(bytes32=>uint) private periods;
mapping(bytes32=>uint) private timeouts; mapping(bytes32=>uint) private timeouts;
mapping(bytes32=>uint) private ends;
mapping(bytes32=>uint) private markers; mapping(bytes32=>uint) private markers;
mapping(bytes32=>uint) private missed; mapping(bytes32=>uint) private missed;
mapping(bytes32=>mapping(uint=>bool)) private received; mapping(bytes32=>mapping(uint=>bool)) private received;
@ -19,6 +20,10 @@ contract Proofs {
return timeouts[id]; return timeouts[id];
} }
function _end(bytes32 id) internal view returns (uint) {
return ends[id];
}
function _missed(bytes32 id) internal view returns (uint) { function _missed(bytes32 id) internal view returns (uint) {
return missed[id]; return missed[id];
} }
@ -30,12 +35,18 @@ contract Proofs {
require(timeout <= 128, "Invalid proof timeout, needs to be <= 128"); require(timeout <= 128, "Invalid proof timeout, needs to be <= 128");
} }
function _expectProofs(bytes32 id, uint period, uint timeout) internal { function _expectProofs(
bytes32 id,
uint period,
uint timeout,
uint duration
) internal {
require(!ids[id], "Proof id already in use"); require(!ids[id], "Proof id already in use");
_checkTimeout(timeout); _checkTimeout(timeout);
ids[id] = true; ids[id] = true;
periods[id] = period; periods[id] = period;
timeouts[id] = timeout; timeouts[id] = timeout;
ends[id] = block.number + duration + 2 * timeout;
markers[id] = uint(blockhash(block.number - 1)) % period; markers[id] = uint(blockhash(block.number - 1)) % period;
} }

View File

@ -43,7 +43,7 @@ contract Storage is Contracts, Proofs, Stakes {
requestSignature, requestSignature,
bidSignature bidSignature
); );
_expectProofs(id, _proofPeriod, _proofTimeout); _expectProofs(id, _proofPeriod, _proofTimeout, _duration);
} }
function duration(bytes32 contractId) public view returns (uint) { function duration(bytes32 contractId) public view returns (uint) {

View File

@ -14,12 +14,21 @@ contract TestProofs is Proofs {
return _timeout(id); return _timeout(id);
} }
function end(bytes32 id) public view returns (uint) {
return _end(id);
}
function missed(bytes32 id) public view returns (uint) { function missed(bytes32 id) public view returns (uint) {
return _missed(id); return _missed(id);
} }
function expectProofs(bytes32 id, uint _period, uint _timeout) public { function expectProofs(
_expectProofs(id, _period, _timeout); bytes32 id,
uint _period,
uint _timeout,
uint _duration
) public {
_expectProofs(id, _period, _timeout, _duration);
} }
function isProofRequired( function isProofRequired(

View File

@ -6,6 +6,7 @@ describe("Proofs", function () {
const id = ethers.utils.randomBytes(32) const id = ethers.utils.randomBytes(32)
const period = 10 const period = 10
const timeout = 5 const timeout = 5
const duration = 100
let proofs let proofs
@ -14,40 +15,47 @@ describe("Proofs", function () {
proofs = await Proofs.deploy() proofs = await Proofs.deploy()
}) })
async function mineBlock() {
await ethers.provider.send("evm_mine")
}
async function minedBlockNumber() {
return await ethers.provider.getBlockNumber()
}
it("indicates that proofs are required", async function() { it("indicates that proofs are required", async function() {
await proofs.expectProofs(id, period, timeout) await proofs.expectProofs(id, period, timeout, duration)
expect(await proofs.period(id)).to.equal(period) expect(await proofs.period(id)).to.equal(period)
expect(await proofs.timeout(id)).to.equal(timeout) expect(await proofs.timeout(id)).to.equal(timeout)
}) })
it("calculates an endtime based on duration and timeout", async function() {
await proofs.expectProofs(id, period, timeout, duration)
let start = await minedBlockNumber()
let end = start + duration + 2 * timeout
expect(await proofs.end(id)).to.equal(end)
})
it("does not allow ids to be reused", async function() { it("does not allow ids to be reused", async function() {
await proofs.expectProofs(id, period, timeout) await proofs.expectProofs(id, period, timeout, duration)
await expect( await expect(
proofs.expectProofs(id, period, timeout) proofs.expectProofs(id, period, timeout, duration)
).to.be.revertedWith("Proof id already in use") ).to.be.revertedWith("Proof id already in use")
}) })
it("does not allow a proof timeout that is too large", async function () { it("does not allow a proof timeout that is too large", async function () {
let invalidTimeout = 129 // max proof timeout is 128 blocks let invalidTimeout = 129 // max proof timeout is 128 blocks
await expect( await expect(
proofs.expectProofs(id, period, invalidTimeout) proofs.expectProofs(id, period, invalidTimeout, duration)
).to.be.revertedWith("Invalid proof timeout") ).to.be.revertedWith("Invalid proof timeout")
}) })
describe("when proofs are required", async function () { describe("when proofs are required", async function () {
beforeEach(async function () { beforeEach(async function () {
await proofs.expectProofs(id, period, timeout) await proofs.expectProofs(id, period, timeout, duration)
}) })
async function mineBlock() {
await ethers.provider.send("evm_mine")
}
async function minedBlockNumber() {
return await ethers.provider.getBlockNumber()
}
async function mineUntilProofIsRequired(id) { async function mineUntilProofIsRequired(id) {
while (!await proofs.isProofRequired(id, await minedBlockNumber())) { while (!await proofs.isProofRequired(id, await minedBlockNumber())) {
mineBlock() mineBlock()