provable-things / ethereum-api

Provable API for Ethereum smart contracts
https://docs.provable.xyz/#ethereum
MIT License
801 stars 428 forks source link

Random number proof verification fails if delay is set #22

Closed pabloruiz55 closed 6 years ago

pabloruiz55 commented 7 years ago

If oraclize_newRandomDSQuery(delay, N, callbackGas); is executed with a delay different than 0, when the callback is fired, the oraclize_randomDS_proofVerify__returnCode call will fail verification of proof.

The expected behavior would be for the callback to properly verify the random number generated even if it was delayed.

Tested on ropsten. Here's the code to reproduce it. call scheduleRandomNumOnCreation(0); and it will work properly. -reaches event Testeo(2014)- call scheduleRandomNumOnCreation(30); and the callback will fail the proof verification

pragma solidity ^0.4.4;

import "github.com/oraclize/ethereum-api/oraclizeAPI.sol";

contract Raffle is usingOraclize{

  event Testeo(uint _number);

  function Raffle(){
    scheduleRandomNumOnCreation(0);
  }

   function __callback(bytes32 _queryId, string _result, bytes _proof)
  {
      Testeo(1022);
      // If we already generated a random number, we can't generate a new one.
      // if we reach this point successfully, it means that the attached authenticity proof has passed!
      require (msg.sender == oraclize_cbAddress());

      //Before using the random number we have to check if the minimum amount of participants was reached.
      //If not, we should abort. LATER, when dealing with money, we should also return funds to the participants.

      if (oraclize_randomDS_proofVerify__returnCode(_queryId, _result, _proof) != 0) {
        Testeo(1023);
          // the proof verification has failed, do we need to take any action here? (depends on the use case)
      } else {
          // the proof verification has passed
          Testeo(1024);
          // for simplicity of use, let's also convert the random bytes to uint if we need
          uint maxRange = 100; // this is the highest uint we want to get. It should never be greater than 2^(8*N), where N is the number of random bytes we had asked the datasource to return
          uint randomNumber = uint(sha3(_result)) % maxRange; // this is an efficient way to get the uint out in the [0, maxRange] range
          Testeo(randomNumber);
      }
    }

  function scheduleRandomNumOnCreation(uint _timeFromNow) internal{
    //Called on raffle constructor only
    oraclize_setProof(proofType_Ledger); // sets the Ledger authenticity proof in the constructor
    uint N = 4; // number of random bytes we want the datasource to return
    uint delay = _timeFromNow; // number of seconds to wait before the execution takes place
    uint callbackGas = 200000; // amount of gas we want Oraclize to set for the callback function
    bytes32 queryId = oraclize_newRandomDSQuery(delay, N, callbackGas); // this function internally generates the correct oraclize_query and returns its queryId

  }

}
bertani commented 7 years ago

Good catch, this is due to a missing implementation in the Solidity verification function of the time delay option (when it is != 0). Let's keep this issue open to keep track of the progress: we will update the Solidity verification function soon to support any delay.

vlad-khramov commented 6 years ago

Any news?

borisblizzard commented 6 years ago

I'm also wondering whether this has been fixed yet since I need this functionality.

bertani commented 6 years ago

@quantum13 @borisblizzard by using the latest version of the oraclizeAPI you will be able to set a randomDS delay up to 120 seconds (~8 blocks on mainnet). This is already quite a stronger guarantee compared to having 0 delay (default). If you need to schedule the query for a future execution you can still call oraclize_query with a non-zero first argument.

I hope this answers to your question, let us know if you need anything else!

vlad-khramov commented 6 years ago

@bertani thanks, but it is still not working, even with delay=0: contract (with source): https://rinkeby.etherscan.io/address/0x1602863d2c4c7f9f074109d56b37e3b43b8220c4 tx (empty proof): https://rinkeby.etherscan.io/tx/0x3fb3fdf669cea9c9e1e31728f18d5cc773d385bb57528a2db9fcc8bd481823bc

100 seconds (empty proof): https://rinkeby.etherscan.io/address/0x315de0d342c51a8d85b86973165ff915724eb4a6 60 seconds (empty proof): https://rinkeby.etherscan.io/address/0x2495ed1baebf72b9d4884f0c3f7e052eeeea6473

45 sec (wrong proof): https://rinkeby.etherscan.io/address/0x1a53827c79ac8ec41ebc88dcc50d527a1ef1f700

10 sec (wrong proof): https://rinkeby.etherscan.io/address/0x5d791cd29d9a531e0083f1f9491a8d128aacb1d2

0 sec: https://rinkeby.etherscan.io/address/0xcb7f922e95bac08544cdea6d6dd9ba6c0e6e2e27

borisblizzard commented 6 years ago

Actually I noticed that rand stopped working on Rinkeby myself. Main net still works fine.

jfdelgad commented 6 years ago

Not working on Rinkeby, I am suing Oraclize 'RandomExample' and the proof fails all the time, but the ether is deducted from my account!!. Also, I am a bit concern about the amount of gas that takes to deploy the contract, It hits the limits and is impossible to deploy the contract as it is, I had to remove the call to update in the constructor to be able to deploy the contract.

Nathisgreen commented 6 years ago

I am also finding it isn't working on Rinkeby even when set to 0. Always failing the proof verification.

D-Nice commented 6 years ago

The Random DS on Rinkeby is confirmed to be working now. Please try again.

Specifically in regards to Rinkeby, it appears to work with up to a 54 second delay.

VanijaDev commented 5 years ago

Hello! I am fighting with randomness error for a day already...

  1. I have set up oraclize-truffle-box from here - https://github.com/oraclize/truffle-starter
  2. unit tests works fine;
  3. edited my code for randomness with "oraclize_newRandomDSQuery"
  4. run unit tests - fails. 4.1. run my code in Remix with "remixd" - works.
  5. changed query to - "oraclize_query("URL", "xml(https://www.fueleconomy.gov/ws/rest/fuelprices).fuelPrices.diesel");" - works;
  6. again changed to - "oraclize_query("URL", "json(https://api.kraken.com/0/public/Ticker?pair=ETHXBT).result.XETHXXBT.c.0");" - works again;
  7. edited "N", "delay", "callbackGas" in "oraclize_newRandomDSQuery" - nothing works...

why is that..?

screen shot 2019-03-05 at 18 46 12
D-Nice commented 5 years ago

@VanijaDev Are you trying to run that from the Javascript VM of Remix? The random DS only works on mainnet and public testnets as per: https://github.com/oraclize/ethereum-examples/tree/master/solidity/random-datasource