-
Notifications
You must be signed in to change notification settings - Fork 581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add ERC: Quantum Supremacy Bounty #731
base: master
Are you sure you want to change the base?
Changes from all commits
d20374e
133bb67
5684780
577a1dd
eade2f4
2cf3746
afc736d
c9fa82a
efcb474
7a17213
49f5764
cecfcda
3227ca5
c5f9487
29d3f91
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.12; | ||
|
||
import "@openzeppelin/contracts/utils/Address.sol"; | ||
import "./support/CommitRevealManager.sol"; | ||
import "./support/LockManager.sol"; | ||
|
||
abstract contract BountyContract { | ||
bool public solved; | ||
|
||
mapping(address => mapping(uint256 => Commit)) private commits; | ||
Locks private locksDefault; | ||
|
||
constructor(uint256 numberOfLocksArg) { | ||
locksDefault = LockManager.init(numberOfLocksArg); | ||
} | ||
|
||
modifier requireUnsolved() { | ||
require(!solved, 'Already solved'); | ||
_; | ||
} | ||
|
||
function locks() internal view virtual returns (Locks storage) { | ||
return locksDefault; | ||
} | ||
|
||
function _verifySolution(uint256 lockNumber, bytes memory solution) internal view virtual returns (bool); | ||
|
||
function getLock(uint256 lockNumber) public view returns (bytes[] memory) { | ||
return LockManager.getLock(locks(), lockNumber); | ||
} | ||
|
||
function numberOfLocks() public view returns (uint256) { | ||
return locks().numberOfLocks; | ||
} | ||
|
||
function commitSolution(uint256 lockNumber, bytes memory solutionHash) public requireUnsolved { | ||
CommitRevealManager.commitSolution(commits, msg.sender, lockNumber, solutionHash); | ||
} | ||
|
||
function getMyCommit(uint256 lockNumber) public view returns (bytes memory, uint256) { | ||
return CommitRevealManager.getMyCommit(commits, msg.sender, lockNumber); | ||
} | ||
|
||
function solve(uint256 lockNumber, bytes memory solution) public requireUnsolved { | ||
require(CommitRevealManager.verifyReveal(commits, msg.sender, lockNumber, solution), "Solution hash doesn't match"); | ||
require(_verifySolution(lockNumber, solution), 'Invalid solution'); | ||
|
||
LockManager.setLocksSolvedStatus(locks(), lockNumber, true); | ||
if (LockManager.allLocksSolved(locks())) { | ||
solved = true; | ||
_sendBountyToSolver(); | ||
} | ||
} | ||
|
||
function _sendBountyToSolver() private { | ||
Address.sendValue(payable(msg.sender), bounty()); | ||
} | ||
|
||
function bounty() public view returns (uint256) { | ||
return address(this).balance; | ||
} | ||
|
||
receive() external payable { | ||
addToBounty(); | ||
} | ||
|
||
fallback() external payable { | ||
addToBounty(); | ||
} | ||
|
||
function addToBounty() public payable requireUnsolved { | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
pragma solidity ^0.8.12; | ||
|
||
import "../BountyContract.sol"; | ||
import "../support/BigNumbers.sol"; | ||
|
||
abstract contract OrderFindingBounty is BountyContract { | ||
using BigNumbers for *; | ||
|
||
constructor(uint256 numberOfLocks) BountyContract(numberOfLocks) {} | ||
|
||
function _verifySolution(uint256 lockNumber, bytes memory solution) internal view override returns (bool) { | ||
bytes[] memory lock = getLock(lockNumber); | ||
require(lock.length > 0, 'Lock has not been generated yet.'); | ||
bytes memory modulus = lock[0]; | ||
bytes memory base = lock[1]; | ||
|
||
BigNumber memory answer = base.init(false).modexp(solution.init(false), modulus.init(false)); | ||
return answer.eq(BigNumbers.one()); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,123 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
pragma solidity ^0.8.12; | ||
|
||
import "@openzeppelin/contracts/utils/math/Math.sol"; | ||
import "solidity-bytes-utils/contracts/BytesLib.sol"; | ||
import "../../support/AccumulatorUtils.sol"; | ||
import "../../support/BigNumbers.sol"; | ||
import "../../support/LockManager.sol"; | ||
|
||
struct Accumulator { | ||
Locks locks; | ||
bool generationIsDone; | ||
uint8 parametersPerLock; | ||
|
||
bytes _currentBytes; | ||
uint256 _currentLockNumber; | ||
uint256 _bytesPerLock; | ||
|
||
BigNumber _a; | ||
BigNumber _b; | ||
BigNumber _baseToCheck; | ||
uint256 _gcdIterationsPerCall; | ||
} | ||
|
||
|
||
library OrderFindingAccumulator { | ||
using BigNumbers for *; | ||
|
||
uint8 private constant _BITS_PER_BYTE = 8; | ||
|
||
function init(uint256 numberOfLocks, uint256 bytesPerLock, uint256 gcdIterationsPerCall) internal pure returns (Accumulator memory accumulator) | ||
{ | ||
accumulator.locks = LockManager.init(numberOfLocks); | ||
accumulator.parametersPerLock = 2; | ||
accumulator._bytesPerLock = bytesPerLock; | ||
accumulator._gcdIterationsPerCall = gcdIterationsPerCall; | ||
return accumulator; | ||
} | ||
|
||
function accumulate(Accumulator storage accumulator, bytes memory randomBytes) internal { | ||
if (accumulator.generationIsDone) return; | ||
if (accumulator._baseToCheck.bitlen > 0) { | ||
_isCoprime(accumulator); | ||
return; | ||
} | ||
|
||
accumulator._currentBytes = AccumulatorUtils.getRemainingBytes(randomBytes, accumulator._currentBytes, accumulator._bytesPerLock); | ||
if (accumulator._currentBytes.length >= accumulator._bytesPerLock) { | ||
if (accumulator.locks.vals[accumulator._currentLockNumber].length == 0) { | ||
accumulator.locks.vals[accumulator._currentLockNumber] = new bytes[](accumulator.parametersPerLock); | ||
} | ||
|
||
if (accumulator.locks.vals[accumulator._currentLockNumber][0].length == 0) { | ||
_setFirstBit(accumulator._currentBytes); | ||
accumulator.locks.vals[accumulator._currentLockNumber][0] = accumulator._currentBytes; | ||
} else { | ||
BigNumber memory modulus = accumulator.locks.vals[accumulator._currentLockNumber][0].init(false); | ||
BigNumber memory base = accumulator._currentBytes.init(false).mod(modulus); | ||
BigNumber memory negativeOne = modulus.sub(BigNumbers.one()); | ||
|
||
bool hasTrivialOrder = base.eq(BigNumbers.one()) || base.eq(negativeOne); | ||
if (!hasTrivialOrder) { | ||
accumulator._a = modulus; | ||
accumulator._b = accumulator._baseToCheck = base; | ||
return; | ||
} | ||
} | ||
_resetBytes(accumulator); | ||
} | ||
} | ||
|
||
function _setFirstBit(bytes storage value) private { | ||
value[0] |= bytes1(uint8(1 << 7)); | ||
} | ||
|
||
/* Adapted rom https://gist.github.com/3esmit/8c0a63f17f2f2448cc1576eb27fe5910 | ||
*/ | ||
function _isCoprime(Accumulator storage accumulator) private { | ||
BigNumber memory a = accumulator._a; | ||
BigNumber memory b = accumulator._b; | ||
for (uint256 i = 0; i < accumulator._gcdIterationsPerCall; i++) { | ||
bool checkIsFinished = b.isZero(); | ||
if (checkIsFinished) { | ||
bool isCoprime = a.eq(BigNumbers.one()); | ||
if (isCoprime) _setBase(accumulator); | ||
_resetBytes(accumulator); | ||
return; | ||
} else { | ||
BigNumber memory temp = b; | ||
b = a.mod(b); | ||
a = temp; | ||
} | ||
} | ||
accumulator._a = a; | ||
accumulator._b = b; | ||
} | ||
|
||
function _setBase(Accumulator storage accumulator) private { | ||
accumulator.locks.vals[accumulator._currentLockNumber][1] = _slicePrefix(accumulator); | ||
++accumulator._currentLockNumber; | ||
if (accumulator._currentLockNumber >= accumulator.locks.numberOfLocks) accumulator.generationIsDone = true; | ||
} | ||
|
||
function _slicePrefix(Accumulator storage accumulator) private view returns (bytes memory) { | ||
bytes memory value = accumulator._baseToCheck.val; | ||
return BytesLib.slice(value, value.length - accumulator._bytesPerLock, accumulator._bytesPerLock); | ||
} | ||
|
||
function _resetBytes(Accumulator storage accumulator) private { | ||
accumulator._currentBytes = ''; | ||
accumulator._a = BigNumber('', false, 0); | ||
accumulator._b = BigNumber('', false, 0); | ||
accumulator._baseToCheck = BigNumber('', false, 0); | ||
} | ||
|
||
function isCheckingPrime(Accumulator storage accumulator) internal view returns (bool) { | ||
return accumulator._baseToCheck.bitlen > 0; | ||
} | ||
|
||
function currentPrimeCheck(Accumulator storage accumulator) internal view returns (bytes memory) { | ||
return accumulator._b.val; | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same |
||
pragma solidity ^0.8.12; | ||
|
||
import "./OrderFindingAccumulator.sol"; | ||
|
||
contract OrderFindingAccumulatorTestHelper { | ||
Accumulator public accumulator; | ||
|
||
constructor(uint256 numberOfLocks, uint256 bytesPerPrime, uint256 gcdIterationsPerCall) { | ||
accumulator = OrderFindingAccumulator.init(numberOfLocks, bytesPerPrime, gcdIterationsPerCall); | ||
} | ||
|
||
function triggerAccumulate(bytes memory randomBytes) public { | ||
OrderFindingAccumulator.accumulate(accumulator, randomBytes); | ||
} | ||
|
||
function isCheckingPrime() public view returns (bool) { | ||
return OrderFindingAccumulator.isCheckingPrime(accumulator); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Big reference implementation! For all the files, no GPL. |
||
pragma solidity ^0.8.12; | ||
|
||
import "./OrderFindingAccumulator.sol"; | ||
import "../OrderFindingBounty.sol"; | ||
|
||
|
||
contract OrderFindingBountyWithLockGeneration is OrderFindingBounty { | ||
uint256 private iteration; | ||
|
||
Accumulator private orderFindingAccumulator; | ||
|
||
constructor(uint256 numberOfLocks, uint256 byteSizeOfModulus, uint256 gcdIterationsPerCall) | ||
OrderFindingBounty(numberOfLocks) | ||
{ | ||
orderFindingAccumulator = OrderFindingAccumulator.init(numberOfLocks, byteSizeOfModulus, gcdIterationsPerCall); | ||
} | ||
|
||
function locks() internal view override returns (Locks storage) { | ||
return orderFindingAccumulator.locks; | ||
} | ||
|
||
function isCheckingPrime() public view returns (bool) { | ||
return OrderFindingAccumulator.isCheckingPrime(orderFindingAccumulator); | ||
} | ||
|
||
function currentPrimeCheck() public view returns (bytes memory) { | ||
return OrderFindingAccumulator.currentPrimeCheck(orderFindingAccumulator); | ||
} | ||
|
||
function triggerLockAccumulation() public { | ||
require(!orderFindingAccumulator.generationIsDone, 'Locks have already been generated'); | ||
bytes memory randomNumber = ''; | ||
if (!OrderFindingAccumulator.isCheckingPrime(orderFindingAccumulator)) randomNumber = _generateRandomBytes(); | ||
OrderFindingAccumulator.accumulate(orderFindingAccumulator, randomNumber); | ||
} | ||
|
||
function generationIsDone() public view returns (bool) { | ||
return orderFindingAccumulator.generationIsDone; | ||
} | ||
|
||
function _generateRandomBytes() private returns (bytes memory) { | ||
return abi.encodePacked(keccak256(abi.encodePacked(block.difficulty, iteration++))); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.12; | ||
|
||
import "../OrderFindingBounty.sol"; | ||
|
||
contract OrderFindingBountyWithPredeterminedLocks is OrderFindingBounty { | ||
constructor(uint256 numberOfLocks) | ||
OrderFindingBounty(numberOfLocks) {} | ||
|
||
function setLock(uint256 lockNumber, bytes[] memory lock) public { | ||
LockManager.setLock(locks(), lockNumber, lock); | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
// SPDX-License-Identifier: GPL-3.0 | ||
pragma solidity ^0.8.12; | ||
|
||
import "@chainlink/contracts/src/v0.8/VRFConsumerBase.sol"; | ||
import "solidity-bytes-utils/contracts/BytesLib.sol"; | ||
|
||
import "../BountyContract.sol"; | ||
import "../support/BigNumbers.sol"; | ||
import "./miller-rabin/MillerRabin.sol"; | ||
|
||
abstract contract PrimeFactoringBounty is BountyContract { | ||
using BigNumbers for *; | ||
|
||
constructor(uint256 numberOfLocks) BountyContract(numberOfLocks) {} | ||
|
||
function _verifySolution(uint256 lockNumber, bytes memory solution) internal view override returns (bool) { | ||
bytes[] memory primes = abi.decode(solution, (bytes[])); | ||
BigNumber memory product = BigNumbers.one(); | ||
for (uint256 i = 0; i < primes.length; i++) { | ||
bytes memory primeFactor = primes[i]; | ||
require(MillerRabin.isPrime(primeFactor), 'Given solution is not prime'); | ||
product = product.mul(primeFactor.init(false)); | ||
} | ||
|
||
BigNumber memory lock = getLock(lockNumber)[0].init(false); | ||
return product.eq(lock); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We cannot accept GPL'd code. It would carry over to any implementation based on this reference implementation.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Which license would you recommend? Or should we just remove this line altogether?