docs: proofs comments (#118)
Co-authored-by: Eric <5089238+emizzle@users.noreply.github.com> Co-authored-by: markspanbroek <mark@spanbroek.net>
This commit is contained in:
parent
74b1a9efb7
commit
fe8da1013d
|
@ -6,10 +6,18 @@ import "./Requests.sol";
|
||||||
import "./Periods.sol";
|
import "./Periods.sol";
|
||||||
import "./Groth16.sol";
|
import "./Groth16.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title Proofs
|
||||||
|
* @notice Abstract contract that handles proofs tracking, validation and reporting functionality
|
||||||
|
*/
|
||||||
abstract contract Proofs is Periods {
|
abstract contract Proofs is Periods {
|
||||||
ProofConfig private _config;
|
ProofConfig private _config;
|
||||||
IGroth16Verifier private _verifier;
|
IGroth16Verifier private _verifier;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creation of the contract requires at least 256 mined blocks!
|
||||||
|
* @param config Proving configuration
|
||||||
|
*/
|
||||||
constructor(
|
constructor(
|
||||||
ProofConfig memory config,
|
ProofConfig memory config,
|
||||||
IGroth16Verifier verifier
|
IGroth16Verifier verifier
|
||||||
|
@ -19,27 +27,46 @@ abstract contract Proofs is Periods {
|
||||||
_verifier = verifier;
|
_verifier = verifier;
|
||||||
}
|
}
|
||||||
|
|
||||||
mapping(SlotId => uint256) private _slotStarts;
|
mapping(SlotId => uint256) private _slotStarts; // TODO: Should be smaller than uint256
|
||||||
mapping(SlotId => uint256) private _probabilities;
|
mapping(SlotId => uint256) private _probabilities;
|
||||||
mapping(SlotId => uint256) private _missed;
|
mapping(SlotId => uint256) private _missed; // TODO: Should be smaller than uint256
|
||||||
mapping(SlotId => mapping(Period => bool)) private _received;
|
mapping(SlotId => mapping(Period => bool)) private _received;
|
||||||
mapping(SlotId => mapping(Period => bool)) private _missing;
|
mapping(SlotId => mapping(Period => bool)) private _missing;
|
||||||
|
|
||||||
function slotState(SlotId id) public view virtual returns (SlotState);
|
function slotState(SlotId id) public view virtual returns (SlotState);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return Number of missed proofs since Slot was Filled
|
||||||
|
*/
|
||||||
function missingProofs(SlotId slotId) public view returns (uint256) {
|
function missingProofs(SlotId slotId) public view returns (uint256) {
|
||||||
return _missed[slotId];
|
return _missed[slotId];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param slotId Slot's ID for which the proofs should be reset
|
||||||
|
* @notice Resets the missing proofs counter to zero
|
||||||
|
*/
|
||||||
function _resetMissingProofs(SlotId slotId) internal {
|
function _resetMissingProofs(SlotId slotId) internal {
|
||||||
_missed[slotId] = 0;
|
_missed[slotId] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id Slot's ID for which the proofs should be started to require
|
||||||
|
* @param probability Integer which specifies the probability of how often the proofs will be required. Lower number means higher probability.
|
||||||
|
* @notice Notes down the block's timestamp as Slot's starting time for requiring proofs
|
||||||
|
* and saves the required probability.
|
||||||
|
*/
|
||||||
function _startRequiringProofs(SlotId id, uint256 probability) internal {
|
function _startRequiringProofs(SlotId id, uint256 probability) internal {
|
||||||
_slotStarts[id] = block.timestamp;
|
_slotStarts[id] = block.timestamp;
|
||||||
_probabilities[id] = probability;
|
_probabilities[id] = probability;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id Slot's ID for which the pointer should be calculated
|
||||||
|
* @param period Period for which the pointer should be calculated
|
||||||
|
* @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.
|
||||||
|
* @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)
|
||||||
|
*/
|
||||||
function _getPointer(SlotId id, Period period) internal view returns (uint8) {
|
function _getPointer(SlotId id, Period period) internal view returns (uint8) {
|
||||||
uint256 blockNumber = block.number % 256;
|
uint256 blockNumber = block.number % 256;
|
||||||
// To ensure the pointer does not remain in downtime for many consecutive
|
// To ensure the pointer does not remain in downtime for many consecutive
|
||||||
|
@ -51,16 +78,30 @@ abstract contract Proofs is Periods {
|
||||||
return uint8(pointer);
|
return uint8(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id Slot's ID for which the pointer should be calculated
|
||||||
|
* @return Uint8 pointer that is stable over current Period, ie an integer offset [0-255] of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.
|
||||||
|
* @dev For more information see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md)
|
||||||
|
*/
|
||||||
function getPointer(SlotId id) public view returns (uint8) {
|
function getPointer(SlotId id) public view returns (uint8) {
|
||||||
return _getPointer(id, _blockPeriod());
|
return _getPointer(id, _blockPeriod());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param pointer Integer [0-255] that indicates an offset of the last 256 blocks, pointing to a block that remains constant for the entire Period's duration.
|
||||||
|
* @return Challenge that should be used for generation of proofs
|
||||||
|
*/
|
||||||
function _getChallenge(uint8 pointer) internal view returns (bytes32) {
|
function _getChallenge(uint8 pointer) internal view returns (bytes32) {
|
||||||
bytes32 hash = blockhash(block.number - 1 - pointer);
|
bytes32 hash = blockhash(block.number - 1 - pointer);
|
||||||
assert(uint256(hash) != 0);
|
assert(uint256(hash) != 0);
|
||||||
return keccak256(abi.encode(hash));
|
return keccak256(abi.encode(hash));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id Slot's ID for which the challenge should be calculated
|
||||||
|
* @param period Period for which the challenge should be calculated
|
||||||
|
* @return Challenge that should be used for generation of proofs
|
||||||
|
*/
|
||||||
function _getChallenge(
|
function _getChallenge(
|
||||||
SlotId id,
|
SlotId id,
|
||||||
Period period
|
Period period
|
||||||
|
@ -68,10 +109,18 @@ abstract contract Proofs is Periods {
|
||||||
return _getChallenge(_getPointer(id, period));
|
return _getChallenge(_getPointer(id, period));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id Slot's ID for which the challenge should be calculated
|
||||||
|
* @return Challenge for current Period that should be used for generation of proofs
|
||||||
|
*/
|
||||||
function getChallenge(SlotId id) public view returns (bytes32) {
|
function getChallenge(SlotId id) public view returns (bytes32) {
|
||||||
return _getChallenge(id, _blockPeriod());
|
return _getChallenge(id, _blockPeriod());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id Slot's ID for which the requirements are gathered. If the Slot's state is other than Filled, `false` is always returned.
|
||||||
|
* @param period Period for which the requirements are gathered.
|
||||||
|
*/
|
||||||
function _getProofRequirement(
|
function _getProofRequirement(
|
||||||
SlotId id,
|
SlotId id,
|
||||||
Period period
|
Period period
|
||||||
|
@ -83,10 +132,16 @@ abstract contract Proofs is Periods {
|
||||||
}
|
}
|
||||||
pointer = _getPointer(id, period);
|
pointer = _getPointer(id, period);
|
||||||
bytes32 challenge = _getChallenge(pointer);
|
bytes32 challenge = _getChallenge(pointer);
|
||||||
|
|
||||||
|
/// Scaling of the probability according the downtime configuration
|
||||||
|
/// See: https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime
|
||||||
uint256 probability = (_probabilities[id] * (256 - _config.downtime)) / 256;
|
uint256 probability = (_probabilities[id] * (256 - _config.downtime)) / 256;
|
||||||
isRequired = probability == 0 || uint256(challenge) % probability == 0;
|
isRequired = probability == 0 || uint256(challenge) % probability == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* See isProofRequired
|
||||||
|
*/
|
||||||
function _isProofRequired(
|
function _isProofRequired(
|
||||||
SlotId id,
|
SlotId id,
|
||||||
Period period
|
Period period
|
||||||
|
@ -97,10 +152,24 @@ abstract contract Proofs is Periods {
|
||||||
return isRequired && pointer >= _config.downtime;
|
return isRequired && pointer >= _config.downtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param id Slot's ID for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.
|
||||||
|
* @return bool indicating if proof is required for current period
|
||||||
|
*/
|
||||||
function isProofRequired(SlotId id) public view returns (bool) {
|
function isProofRequired(SlotId id) public view returns (bool) {
|
||||||
return _isProofRequired(id, _blockPeriod());
|
return _isProofRequired(id, _blockPeriod());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Proof Downtime specifies part of the Period when the proof is not required even
|
||||||
|
* if the proof should be required. This function returns true if the pointer is
|
||||||
|
* in downtime (hence no proof required now) and at the same time the proof
|
||||||
|
* will be required later on in the Period.
|
||||||
|
*
|
||||||
|
* @dev for more info about downtime see [timing of storage proofs](https://github.com/codex-storage/codex-research/blob/41c4b4409d2092d0a5475aca0f28995034e58d14/design/storage-proof-timing.md#pointer-downtime)
|
||||||
|
* @param id SlotId for which the proof requirements should be checked. If the Slot's state is other than Filled, `false` is always returned.
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
function willProofBeRequired(SlotId id) public view returns (bool) {
|
function willProofBeRequired(SlotId id) public view returns (bool) {
|
||||||
bool isRequired;
|
bool isRequired;
|
||||||
uint8 pointer;
|
uint8 pointer;
|
||||||
|
@ -108,6 +177,15 @@ abstract contract Proofs is Periods {
|
||||||
return isRequired && pointer < _config.downtime;
|
return isRequired && pointer < _config.downtime;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function used for submitting and verification of the proofs.
|
||||||
|
*
|
||||||
|
* @dev Reverts when proof is invalid or had been already submitted.
|
||||||
|
* @dev Emits ProofSubmitted event.
|
||||||
|
* @param id Slot's ID for which the proof requirements should be checked
|
||||||
|
* @param proof Groth16 proof
|
||||||
|
* @param pubSignals Proofs public input
|
||||||
|
*/
|
||||||
function _proofReceived(
|
function _proofReceived(
|
||||||
SlotId id,
|
SlotId id,
|
||||||
Groth16Proof calldata proof,
|
Groth16Proof calldata proof,
|
||||||
|
@ -119,6 +197,17 @@ abstract contract Proofs is Periods {
|
||||||
emit ProofSubmitted(id);
|
emit ProofSubmitted(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Function used to mark proof as missing.
|
||||||
|
*
|
||||||
|
* @param id Slot's ID for which the proof is missing
|
||||||
|
* @param missedPeriod Period for which the proof was missed
|
||||||
|
* @dev Reverts when:
|
||||||
|
* - missedPeriod has not ended yet ended
|
||||||
|
* - missing proof was time-barred
|
||||||
|
* - proof was not required for missedPeriod period
|
||||||
|
* - proof was already marked as missing
|
||||||
|
*/
|
||||||
function _markProofAsMissing(SlotId id, Period missedPeriod) internal {
|
function _markProofAsMissing(SlotId id, Period missedPeriod) internal {
|
||||||
uint256 end = _periodEnd(missedPeriod);
|
uint256 end = _periodEnd(missedPeriod);
|
||||||
require(end < block.timestamp, "Period has not ended yet");
|
require(end < block.timestamp, "Period has not ended yet");
|
||||||
|
|
Loading…
Reference in New Issue