From 476956c4d5637541270340fcdb35976487185ea4 Mon Sep 17 00:00:00 2001 From: Mark Spanbroek Date: Thu, 10 Mar 2022 10:12:03 +0100 Subject: [PATCH] Replace pointer duos with pointer downtime design --- contracts/Proofs.sol | 69 +++++++++++++++++++++----------------------- test/Proofs.test.js | 4 +-- test/examples.js | 2 +- 3 files changed, 36 insertions(+), 39 deletions(-) diff --git a/contracts/Proofs.sol b/contracts/Proofs.sol index e2d2262..ba536b3 100644 --- a/contracts/Proofs.sol +++ b/contracts/Proofs.sol @@ -57,38 +57,30 @@ contract Proofs { markers[id] = uint256(blockhash(block.number - 1)) % period; } - function _getChallenges(bytes32 id, uint256 proofperiod) + function _getPointer(bytes32 id, uint256 proofPeriod) internal view - returns (Challenge memory challenge1, Challenge memory challenge2) + returns (uint8) { - if ( - proofperiod <= periodOf(starts[id]) || proofperiod >= periodOf(ends[id]) - ) { - bytes32 nullChallenge; - return (Challenge(false, nullChallenge), Challenge(false, nullChallenge)); - } + uint256 blockNumber = block.number % 256; + uint256 periodNumber = proofPeriod % 256; + uint256 idOffset = uint256(id) % 256; + uint256 pointer = (blockNumber + periodNumber + idOffset) % 256; + return uint8(pointer); + } - uint256 blocknumber = block.number % 256; - uint256 periodnumber = proofperiod % 256; - uint256 idoffset = uint256(id) % 256; + function _getChallenge(uint8 pointer) internal view returns (bytes32) { + bytes32 hash = blockhash(block.number - 1 - pointer); + assert(uint256(hash) != 0); + return keccak256(abi.encode(hash)); + } - uint256 pointer1 = (blocknumber + periodnumber + idoffset) % 256; - uint256 pointer2 = (blocknumber + periodnumber + idoffset + 128) % 256; - - bytes32 blockhash1 = blockhash(block.number - 1 - pointer1); - bytes32 blockhash2 = blockhash(block.number - 1 - pointer2); - - assert(uint256(blockhash1) != 0); - assert(uint256(blockhash2) != 0); - - challenge1.challenge = keccak256(abi.encode(blockhash1)); - challenge2.challenge = keccak256(abi.encode(blockhash2)); - - challenge1.isProofRequired = - uint256(challenge1.challenge) % probabilities[id] == 0; - challenge2.isProofRequired = - uint256(challenge2.challenge) % probabilities[id] == 0; + function _getChallenge(bytes32 id, uint256 proofPeriod) + internal + view + returns (bytes32) + { + return _getChallenge(_getPointer(id, proofPeriod)); } function _isProofRequired(bytes32 id, uint256 proofPeriod) @@ -96,10 +88,20 @@ contract Proofs { view returns (bool) { - Challenge memory challenge1; - Challenge memory challenge2; - (challenge1, challenge2) = _getChallenges(id, proofPeriod); - return challenge1.isProofRequired && challenge2.isProofRequired; + if (proofPeriod <= periodOf(starts[id])) { + return false; + } + if (proofPeriod >= periodOf(ends[id])) { + return false; + } + uint8 pointer = _getPointer(id, proofPeriod); + // TODO: make configurable: + if (pointer < 64) { + return false; + } + bytes32 challenge = _getChallenge(pointer); + uint256 probability = (probabilities[id] * (256 - 64)) / 256; + return uint256(challenge) % probability == 0; } function _isProofRequired(bytes32 id) internal view returns (bool) { @@ -122,9 +124,4 @@ contract Proofs { missing[id][missedPeriod] = true; missed[id] += 1; } - - struct Challenge { - bool isProofRequired; - bytes32 challenge; - } } diff --git a/test/Proofs.test.js b/test/Proofs.test.js index c75b2e9..ea8d29e 100644 --- a/test/Proofs.test.js +++ b/test/Proofs.test.js @@ -15,7 +15,7 @@ describe("Proofs", function () { const period = 10 const timeout = 5 const duration = 1000 - const probability = 2 // require a proof roughly once every 2² periods + const probability = 4 // require a proof roughly once every 4 periods let proofs @@ -53,7 +53,7 @@ describe("Proofs", function () { } await advanceTime(period) } - let expected = 100 / probability ** 2 + let expected = 100 / probability expect(amount).to.be.closeTo(expected, expected / 2) }) diff --git a/test/examples.js b/test/examples.js index a1e3c06..0a98a28 100644 --- a/test/examples.js +++ b/test/examples.js @@ -7,7 +7,7 @@ const exampleRequest = () => ({ duration: hours(10), size: 1 * 1024 * 1024 * 1024, // 1 Gigabyte contentHash: sha256("0xdeadbeef"), - proofProbability: 2, // require a proof roughly once every 2² periods + proofProbability: 4, // require a proof roughly once every 4 periods maxPrice: 84, expiry: now() + hours(1), nonce: hexlify(randomBytes(32)),