[Proofs] Extract period related types and function

This commit is contained in:
Mark Spanbroek 2023-01-10 14:16:32 +01:00 committed by markspanbroek
parent c0690cd5d1
commit ad155be5a1
4 changed files with 68 additions and 43 deletions

View File

@ -129,7 +129,7 @@ contract Marketplace is Collateral, Proofs {
function markProofAsMissing(
SlotId slotId,
uint256 period
Period period
) public slotMustAcceptProofs(slotId) {
_markProofAsMissing(slotId, period);
address host = getHost(slotId);
@ -313,7 +313,7 @@ contract Marketplace is Collateral, Proofs {
}
function proofPeriod() public view returns (uint256) {
return _period();
return secondsPerPeriod;
}
function proofTimeout() public view returns (uint256) {

40
contracts/Periods.sol Normal file
View File

@ -0,0 +1,40 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.8;
contract Periods {
type Period is uint256;
uint256 internal immutable secondsPerPeriod;
constructor(uint256 _secondsPerPeriod) {
secondsPerPeriod = _secondsPerPeriod;
}
function periodOf(uint256 timestamp) internal view returns (Period) {
return Period.wrap(timestamp / secondsPerPeriod);
}
function blockPeriod() internal view returns (Period) {
return periodOf(block.timestamp);
}
function nextPeriod(Period period) internal pure returns (Period) {
return Period.wrap(Period.unwrap(period) + 1);
}
function periodStart(Period period) internal view returns (uint256) {
return Period.unwrap(period) * secondsPerPeriod;
}
function periodEnd(Period period) internal view returns (uint256) {
return periodStart(nextPeriod(period));
}
function isBefore(Period a, Period b) internal pure returns (bool) {
return Period.unwrap(a) < Period.unwrap(b);
}
function isAfter(Period a, Period b) internal pure returns (bool) {
return isBefore(b, a);
}
}

View File

@ -2,15 +2,18 @@
pragma solidity ^0.8.8;
import "./Requests.sol";
import "./Periods.sol";
abstract contract Proofs {
uint256 private immutable period;
abstract contract Proofs is Periods {
uint256 private immutable timeout;
uint8 private immutable downtime;
constructor(uint256 __period, uint256 __timeout, uint8 __downtime) {
constructor(
uint256 __period,
uint256 __timeout,
uint8 __downtime
) Periods(__period) {
require(block.number > 256, "Insufficient block height");
period = __period;
timeout = __timeout;
downtime = __downtime;
}
@ -18,12 +21,8 @@ abstract contract Proofs {
mapping(SlotId => bool) private slotIds;
mapping(SlotId => uint256) private probabilities;
mapping(SlotId => uint256) private missed;
mapping(SlotId => mapping(uint256 => bool)) private received;
mapping(SlotId => mapping(uint256 => bool)) private missing;
function _period() internal view returns (uint256) {
return period;
}
mapping(SlotId => mapping(Period => bool)) private received;
mapping(SlotId => mapping(Period => bool)) private missing;
function _timeout() internal view returns (uint256) {
return timeout;
@ -41,14 +40,6 @@ abstract contract Proofs {
return missed[slotId];
}
function periodOf(uint256 timestamp) private view returns (uint256) {
return timestamp / period;
}
function currentPeriod() private view returns (uint256) {
return periodOf(block.timestamp);
}
/// @notice Informs the contract that proofs should be expected for id
/// @dev Requires that the id is not already in use
/// @param probability The probability that a proof should be expected
@ -65,17 +56,17 @@ abstract contract Proofs {
function _getPointer(
SlotId id,
uint256 proofPeriod
Period proofPeriod
) internal view returns (uint8) {
uint256 blockNumber = block.number % 256;
uint256 periodNumber = proofPeriod % 256;
uint256 periodNumber = Period.unwrap(proofPeriod) % 256;
uint256 idOffset = uint256(SlotId.unwrap(id)) % 256;
uint256 pointer = (blockNumber + periodNumber + idOffset) % 256;
return uint8(pointer);
}
function _getPointer(SlotId id) internal view returns (uint8) {
return _getPointer(id, currentPeriod());
return _getPointer(id, blockPeriod());
}
function _getChallenge(uint8 pointer) internal view returns (bytes32) {
@ -86,24 +77,22 @@ abstract contract Proofs {
function _getChallenge(
SlotId id,
uint256 proofPeriod
Period proofPeriod
) internal view returns (bytes32) {
return _getChallenge(_getPointer(id, proofPeriod));
}
function _getChallenge(SlotId id) internal view returns (bytes32) {
return _getChallenge(id, currentPeriod());
return _getChallenge(id, blockPeriod());
}
function _getProofRequirement(
SlotId id,
uint256 proofPeriod
Period proofPeriod
) internal view returns (bool isRequired, uint8 pointer) {
if (proofPeriod <= periodOf(proofStart(id))) {
return (false, 0);
}
uint256 end = proofEnd(id);
if (proofPeriod >= periodOf(end)) {
Period start = periodOf(proofStart(id));
Period end = periodOf(proofEnd(id));
if (!isAfter(proofPeriod, start) || !isBefore(proofPeriod, end)) {
return (false, 0);
}
pointer = _getPointer(id, proofPeriod);
@ -114,7 +103,7 @@ abstract contract Proofs {
function _isProofRequired(
SlotId id,
uint256 proofPeriod
Period proofPeriod
) internal view returns (bool) {
bool isRequired;
uint8 pointer;
@ -123,25 +112,25 @@ abstract contract Proofs {
}
function _isProofRequired(SlotId id) internal view returns (bool) {
return _isProofRequired(id, currentPeriod());
return _isProofRequired(id, blockPeriod());
}
function _willProofBeRequired(SlotId id) internal view returns (bool) {
bool isRequired;
uint8 pointer;
(isRequired, pointer) = _getProofRequirement(id, currentPeriod());
(isRequired, pointer) = _getProofRequirement(id, blockPeriod());
return isRequired && pointer < downtime;
}
function submitProof(SlotId id, bytes calldata proof) public {
require(proof.length > 0, "Invalid proof"); // TODO: replace by actual check
require(!received[id][currentPeriod()], "Proof already submitted");
received[id][currentPeriod()] = true;
require(!received[id][blockPeriod()], "Proof already submitted");
received[id][blockPeriod()] = true;
emit ProofSubmitted(id, proof);
}
function _markProofAsMissing(SlotId id, uint256 missedPeriod) internal {
uint256 periodEnd = (missedPeriod + 1) * period;
function _markProofAsMissing(SlotId id, Period missedPeriod) internal {
uint256 periodEnd = periodEnd(missedPeriod);
require(periodEnd < block.timestamp, "Period has not ended yet");
require(block.timestamp < periodEnd + timeout, "Validation timed out");
require(!received[id][missedPeriod], "Proof was submitted, not missing");

View File

@ -27,10 +27,6 @@ contract TestProofs is Proofs {
return ends[slotId];
}
function period() public view returns (uint256) {
return _period();
}
function timeout() public view returns (uint256) {
return _timeout();
}
@ -59,7 +55,7 @@ contract TestProofs is Proofs {
return _getPointer(id);
}
function markProofAsMissing(SlotId id, uint256 _period) public {
function markProofAsMissing(SlotId id, Period _period) public {
_markProofAsMissing(id, _period);
}