Skip to content
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 an example to that implements the schema #8

Open
flockonus opened this issue Aug 1, 2018 · 3 comments
Open

Add an example to that implements the schema #8

flockonus opened this issue Aug 1, 2018 · 3 comments

Comments

@flockonus
Copy link
Contributor

flockonus commented Aug 1, 2018

Should make use of the described technique to implement what the README describes

@clemlak
Copy link

clemlak commented Aug 2, 2018

Hello! Here is my first attempt to implement the technique described in the README.
Please note that this is a first draft and many things and verifications are missing.

pragma solidity 0.4.24;


/**
 * @title First attempt to implement a secure RNG, as described here https://github.com/axiomzen/eth-random
 * @author clemlak https://github.com/clemlak
 * @dev This contract is WIP, please don't use it in production!
 */
contract RNG {
  /**
   * @dev Given a number returns a slice of any bits, at certain offset
   * @author flockonus (https://gist.github.com/flockonus/cb75838d78cf544744e7ac95ab3ec431)
   * @param number A number to be sliced
   * @param nbits How many bits long is the new number
   * @param offset How many bits to skip
   * @return A slice of the number, as an uint
   */
  function sliceNumber(uint256 number, uint256 nbits, uint256 offset) public pure returns (uint256) {
    /* Mask is made by shifting left an offset number of times */
    uint256 mask = uint256((2 ** nbits) - 1) << offset;

    /* AND number with mask, and trim to max of nbits bits */
    return uint256((number & mask) >> offset);
  }

  /**
   * @dev Returns an array with random numbers, as described here https://github.com/axiomzen/eth-random
   * @param count How many random numbers will be returned
   * @param power How big the numbers will be (in bits)
   * @return An array with random numbers
   */
  function getRandomNumbers(uint256 count, uint256 power) public view returns (uint256[]) {
    /* We start from the block number and its hash */
    uint256 ddb = uint256(blockhash(block.number - 1));

    uint256 r = uint256(keccak256(abi.encodePacked(ddb - 1)));

    /* If r equals 0, we try with an higher block number */
    while (r == 0) {
      ddb += 256;

      r = uint256(keccak256(abi.encodePacked(ddb - 1)));
    }

    /* We create an array to store our random numbers */
    uint256[] memory numbers = new uint256[](count);

    for (uint256 i = 0; i < count; i += 1) {
      numbers[i] = sliceNumber(r, power, i);
    }

    return numbers;
  }
}

@flockonus
Copy link
Contributor Author

@clemlak the outline for the reveal looks good. There might require some tests around the r == 0 case, but should be little variation required.

numbers[i] = sliceNumber(r, power, i); should probably be numbers[i] = sliceNumber(r, power, i * power); since the offset is in bits

Now one important step missing is a commit function. At a previous time, an internal storage variable must be set for the DDB (> current block number), which then getRandomNumbers can be used for. Otherwise, an attacker could just get the random numbers once it observes a favorable current blockhash.

Thanks for the prompt draft

@chiro-hiro
Copy link

I've an alternative solution with pure bytecode approach:
https://github.com/chiro-hiro/thedivine

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants