Guest User

Untitled

a guest
Mar 22nd, 2018
269
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.71 KB | None | 0 0
  1. pragma solidity ^0.4.18;
  2.  
  3. contract SHA3_512 {
  4. function hash(uint64[8]) pure public returns(uint32[16]) {}
  5. }
  6.  
  7. contract TeikhosBounty {
  8.  
  9. SHA3_512 public sha3_512 = SHA3_512(0xbD6361cC42fD113ED9A9fdbEDF7eea27b325a222); // Mainnet: 0xbD6361cC42fD113ED9A9fdbEDF7eea27b325a222,
  10. // Rinkeby: 0x2513CF99E051De22cEB6cf5f2EaF0dc4065c8F1f
  11.  
  12. struct Commit {
  13. uint timestamp;
  14. bytes32 signature;
  15. }
  16.  
  17. mapping(address => Commit) public commitment;
  18.  
  19. struct Solution {
  20. uint timestamp;
  21. bytes publicKey; // The key that solves the bounty, empty until the correct key has been submitted with authenticate()
  22. }
  23.  
  24. Solution public isSolved;
  25.  
  26. struct Winner {
  27. uint timestamp;
  28. address winner;
  29. }
  30.  
  31. Winner public winner;
  32.  
  33. uint revealPeriod = 7 days; // Let the reveal phase be open a few days, to let anyone who
  34. // has commited prove if they were the first to do so
  35.  
  36.  
  37. enum State { Commit, Reveal, Payout }
  38.  
  39. modifier inState(State _state)
  40. {
  41. if(_state == State.Commit) { require(isSolved.timestamp == 0); }
  42. if(_state == State.Reveal) { require(isSolved.timestamp != 0 && now < isSolved.timestamp + revealPeriod); }
  43. if(_state == State.Payout) { require(isSolved.timestamp != 0 && now > isSolved.timestamp + revealPeriod); }
  44. _;
  45. }
  46.  
  47. // Proof-of-public-key in format 2xbytes32, to support xor operator and ecrecover r, s v format
  48.  
  49. struct PoPk {
  50. bytes32 half1;
  51. bytes32 half2;
  52. }
  53.  
  54. PoPk public proof_of_public_key;
  55.  
  56. function TeikhosBounty() public { // Constructor function, runs when contract is deployed
  57. proof_of_public_key.half1 = hex"ad683919450048215e7c10c3dc3ffca5939ec8f48c057cfe385c7c6f8b754aa7";
  58. proof_of_public_key.half2 = hex"4ce337445bdc24ee86d6c2460073e5b307ae54cdef4b196c660d5ee03f878e81";
  59. }
  60.  
  61. function commit(bytes32 _signature) public inState(State.Commit) { // Commit the solution as sha3(solution, msg.sender)
  62. require(commitment[msg.sender].timestamp == 0);
  63. commitment[msg.sender].signature = _signature;
  64. commitment[msg.sender].timestamp = now;
  65. }
  66.  
  67. function reveal() public inState(State.Reveal) returns (bool success) {
  68. bytes32 signature = commitment[msg.sender].signature;
  69. require(signature.length != 0);
  70.  
  71. if(sha3(isSolved.publicKey, msg.sender) == signature) {
  72.  
  73. success = true; // The correct solution was submitted
  74.  
  75. if(winner.timestamp == 0 || commitment[msg.sender].timestamp < winner.timestamp) {
  76. winner.winner = msg.sender;
  77. winner.timestamp = commitment[msg.sender].timestamp;
  78. }
  79. }
  80. delete commitment[msg.sender];
  81.  
  82. return success;
  83. }
  84.  
  85. function reward() public inState(State.Payout) {
  86. selfdestruct(winner.winner);
  87. }
  88.  
  89. function authenticate(bytes _publicKey) public inState(State.Commit) {
  90.  
  91. bytes memory keyHash = getHash(_publicKey);
  92.  
  93. // Split hash of public key in 2xbytes32, to support xor operator and ecrecover r, s v format
  94.  
  95. bytes32 hash1;
  96. bytes32 hash2;
  97.  
  98. assembly {
  99. hash1 := mload(add(keyHash,0x20))
  100. hash2 := mload(add(keyHash,0x40))
  101. }
  102.  
  103. // Use xor (reverse cipher) to get signature in r, s v format
  104. bytes32 r = proof_of_public_key.half1 ^ hash1;
  105. bytes32 s = proof_of_public_key.half2 ^ hash2;
  106.  
  107. // Get msgHash for use with ecrecover
  108. bytes32 msgHash = keccak256("\x19Ethereum Signed Message:\n64", _publicKey);
  109.  
  110. // Get address from public key
  111. address signer = address(keccak256(_publicKey));
  112.  
  113. // The value v is not known, try both 27 and 28
  114. if(ecrecover(msgHash, 27, r, s) == signer || ecrecover(msgHash, 28, r, s) == signer ) {
  115. isSolved.timestamp = now;
  116. isSolved.publicKey = _publicKey;
  117.  
  118. require(reveal() == true); // The correct solution has to have been commited,
  119. // prevents funds from getting locked in the contract
  120. }
  121. }
  122.  
  123. // A separate method getHash() for converting bytes to uint64[8], which is done since the EVM cannot pass bytes between contracts
  124. // The SHA3_512 logic is in a separate contract to make it easier to read, that contract could be audited on its own, and so on
  125.  
  126. function getHash(bytes _message) view internal returns (bytes messageHash) {
  127.  
  128. // Use SHA3_512 library to get a sha3_512 hash of public key
  129.  
  130. uint64[8] memory input;
  131.  
  132. // The evm is big endian, have to reverse the bytes
  133.  
  134. bytes memory reversed = new bytes(64);
  135.  
  136. for(uint i = 0; i < 64; i++) {
  137. reversed[i] = _message[63 - i];
  138. }
  139.  
  140. for(i = 0; i < 8; i++) {
  141. bytes8 oneEigth;
  142. // Load 8 byte from reversed public key at position 32 + i * 8
  143. assembly {
  144. oneEigth := mload(add(reversed, add(32, mul(i, 8))))
  145. }
  146. input[7 - i] = uint64(oneEigth);
  147. }
  148.  
  149. uint32[16] memory output = sha3_512.hash(input);
  150.  
  151. bytes memory toBytes = new bytes(64);
  152.  
  153. for(i = 0; i < 16; i++) {
  154. bytes4 oneSixteenth = bytes4(output[15 - i]);
  155. // Store 4 byte in keyHash at position 32 + i * 4
  156. assembly { mstore(add(toBytes, add(32, mul(i, 4))), oneSixteenth) }
  157. }
  158.  
  159. messageHash = new bytes(64);
  160.  
  161. for(i = 0; i < 64; i++) {
  162. messageHash[i] = toBytes[63 - i];
  163. }
  164. }
  165.  
  166. // Make it possible to send ETH to the contract with "payable" on the fallback function
  167.  
  168. function() public payable {}
  169.  
  170. }
Add Comment
Please, Sign In to add comment