# Randomness Precompile Spec
We are planning to initially offer the following sources of randomness:
1. Simple Randomness, block author VRF output which also signs `Parent_Block_Hash + Relay_Block_Hash` (updated every block)
1. Slow Randomness Two Epochs Ago, relay chain BABE randomness (`RandomnessFromTwoEpochsAgo` updated every epoch)
1. Slow Randomness One Epoch Ago, relay chain BABE randomness (`RandomnessFromOneEpochAgo` updated every epoch)
The randomness precompile exposes a request-response API wherein responses can be triggered by any signed origin after the required data has been updated.
Solidity contracts that want to use the API to get randomness must implement this callback interface:
```javascript
interface Randomness {
refundAddress(address);
function fulfillRandomness(bytes32 _requestId, uint256 _randomness)
internal virtual;
}
```
* `_requestId`: unique ID for request
* `_randomness`: randomness output
The moonbeam dev team will provide a solidity library to verify the caller origin is the precompile address.
Our EVM will expose a separate precompile interface:
```javascript
interface RandomnessPrecompile {
function requestRandomness(bytes32 _sourceId, bytes32 _salt, uint256 _fee)
public returns (bytes32 requestId);
function executeFulfillment(bytes32 _requestId);
function updateRandomnessFee(bytes32 _requestId, uint256 _newFee);
function instantRawRandomness(bytes32 _sourceId) public returns (uint256 randomness);
function instantRandomness(bytes32 _sourceId, bytes32 _salt) public returns (uint256 randomness);
}
```
## Request API
The request API is:
```javascript
function requestRandomness(bytes32 _sourceId, bytes32 _salt, uint256 _fee)
public returns (bytes32 requestId)
```
* `_sourceId` corresponds to sources of randomness offered
* `_salt`: unique input, to be concatenated with randmness and hashed to ensure unique final output
* `_fee`: funds reserved to execute the fulfillment request when the source of randomness is next updated
There is a deposit for every randomness request. This will likely be expressed as a balances `reserve`. The deposit will be returned when the request is executed or removed from storage.
## Response API
To fulfill a randomness request, any account can call the precompile method `executeFulfillment` with the `_requestId` associated with the request.
```javascript
// calls fulfillRandomness if randomness is ready (has been updated to new unknown since request was made)
function executeFulfillment(bytes32 _requestId);
```
The `_fee` originally input by the requester is used to pay the costs of executing the fulfillment. The excess of fee less execution costs goes to the caller of `executeFulfillment` as an additional incentive.
Internally, `executeFulfillment` gets the most recent randomness value if updated, concatenates it with the `_salt` input, and hashes it to get the random output which the precompile provides by calling `fulfillRandomness`.
There is also a function to update the `_fee` for a request:
```javascript
function updateRandomnessFee(bytes32 _sourceId, uint256 _newFee);
```
This function replaces the existing `_fee` with the `_newFee` iff `_newFee > _fee` and can be called by anyone. The fee pays for the execution of the randomness fulfillment once the source of randomness is sufficiently updated.
## Instant Randomness API
To get the most recent raw randomness:
```javascript
function instantRawRandomness(bytes32 _sourceId) public returns (uint256 randomness);
```
To use the most recent raw randomness with a salt input:
```javascript
function instantRandomness(bytes32 _sourceId, bytes32 _salt) public returns (uint256 randomness);
```
The `_sourceId` corresponds to the source of randomness:
1. Simple Randomness, block author VRF output which also signs `Parent_Block_Hash + Relay_Block_Hash`(updated every block)
1. Slow Randomness, relay chain BABE randomness (at least `RandomnessFromTwoEpochsAgo` updated every epoch)
1. Slow Randomness One Epoch Ago, relay chain BABE randomness (`RandomnessFromOneEpochAgo` updated every epoch)
### Substrate Pallet Implementation Details
Set new epoch randomness in on_initialize
Set new per block randomness via inherent in runtime digest
Map Epoch => (option(rand), num_requests, expiration_date)
Map Requests => (enum(epoch(epoch_to_fulfill)|block_number), contract_address, bytes32 salt)
We are considering
* exposing extrinsic index via precompile to provide another input that would ensure uniqueness of salt (to ensure unique output that used the randomness)
* refunding the difference between `fee` and actual cost of `executeFulfillment` to the original requester, burning it, paying it to the treasury, paying it to the caller of `executeFulfillment`
* encouraging using `contract_address + nonce` as the `_salt` in the docs for implementations
## SECURITY ASSUMPTIONS FOR EACH SOURCE OF RANDOMNESS
### Slow Random
There is a new `RandomnessFromTwoEpochsAgo` every epoch, but each BABE randomness request must wait X epochs (where 2 < X <= 3) for the next random number.
> Epochs are [4 hours on average in Polkadot](https://wiki.polkadot.network/docs/maintain-polkadot-parameters)
### Simple Random
It can be easily withheld by malicious collators (at the cost of not producing the block and not receiving that reward).
#### EXTRA: Get CurrentRandomness from Relay Chain
The BABE randomness actually provides a VRF output by the block author per block. Ideally we would also provide this randomness to users.