On-Chain Random Oracle on EVM

Build your first dice game on DEXON

One of the most interesting features of DEXON is that it has an on-chain random oracle. An “on-chain” random oracle means that the random source is retrieved directly on the chain itself, instead of having to feed it in by external sources.

Most dice games on Ethereum or EOS use block hash or time as random seed, which is prone to attack or bias by the miners or BP. Alternatives exist but they are not very easy to use. Take Ethereum’s Oraclize for example, you can use Oraclize to call random.org’s API and generate a random seed, then Oraclize will call the smart contract callback and feed in the random number when the API call is made. This is not ideal if we want to achieve speedy transactions as it takes at least 1 extra transaction, which increases the cost and latency. Another technique people use is the concept of VRF, but none of these can achieve what DEXON provides—a truly random number.

DEXON achieves this by making use of threshold signature with BLS scheme. After each block is proposed and confirmed, the DKG (Distributed Key Generation) group selected from the DEXON node set signs the block with their DKG public keys. Given an M-of-N threshold signature scheme, one can construct the threshold signature given any M partial signatures. The resulting threshold signature is unpredictable until constructed.

A keen reader might have already spotted the problem here. The threshold signature is only generated after the block is proposed, how do the transactions in the block make use of threshold signature? This is because DEXON does not store the state root on the proposed block, it is later witnessed by later blocks (there will be a separate post explaining this).

Now we have a threshold signature of every block that no one can predict before sending transactions and we can use it as a random seed for the block. DEXON exposes the random seed as a new EVM instruction RAND (0x2F) . In solidity, it is exposed as the rand variable. The actual random value is calculated as follows:

rand = Keccak( Randomness . Caller . Nonce . RandCallIndex )

Where Randomness is the threshold signature of the block, Caller being the contract caller address, Nonce being the account nonce of the caller, and RandCallIndex is number of times OP_RAND is called in the current transaction.

This allows DEXON to generate a deterministic random number that is truly random. The term deterministic here means that, after the random seed is generated, all clients running the EVM can produce the exact same randomness result.

To try out the randomness feature, you can use the Remix IDE link, here. Click on the left panel, thegist section, and you will find the rand.sol example. The code is listed here also:

pragma solidity ^0.4.25;
contract Rand {
uint256 value;
function update() public {
value = rand;
}
function get() view public returns (uint256) {
return value;
}
}

As you can see, when the update() method is called, the contract storage value is set to a random value rand . You can call get() to read out the value and verify that it is always unique.

Conclusion

That’s it! Now building dice games on DEXON is as easy as porting your existing solidity contracts and by replacing your random value with the rand variable—easy peasy!


This post is just one of the post that I will be releasing bi-weekly to talk about DEXON’s internal designs. Please stay tuned if you want to know more about DEXON.

Also, be sure to follow me on twitter @wnhuangtw

👩‍💻 Gitter (DEXON’s official dev chat): https://gitter.im/dexon-foundation/Lobby