warp-contracts / sequencer

4 stars 0 forks source link

Verifiable randomness #26

Open szynwelski opened 1 year ago

szynwelski commented 1 year ago

The goal of the task is to implement the functionality of providing pseudorandom data to the contract. The current implementation of the functionality is described here.

The current solution has the drawback of relying on trust in the sequencer. The sequencer can manipulate the sortKey value, especially the timestamp, to obtain a desired value. However, we believe that it is not doing so. In the new solution, we cannot make that assumption because we assume that malicious nodes can exist in the network.

In the new solution, the evaluation of contract states can start after the production of a block by the sequencer network (the network guarantees that transactions will eventually be included in Arweave through a decentralized relayer mechanism #13). Therefore, it would be great if randomness could be generated by the proposer. However, the proposer cannot know the pseudorandom value at the time of block creation, as it would give them an opportunity for abuse. Therefore, this value must be computed after block finalization.

I see the following solutions that are resilient to malicious actions by 1/3 of the network nodes:

Using Bundlr signature The VRF (Verifiable Random Function) data is calculated by the relayer. The relayer sends the block to Bundlr and receives a signed receipt. Then, it calculates the VRF data, where the input is the hash of the block, interaction ID, and the receipt signature. ➕ Cosmos nodes do not have the ability to cheat because randomness is based on an external trusted source ➖ next area (besides sending to Arweave) where we rely on Bundlr ➖ VRF data is calculated by the relayer only after sending the block to Arweave, this data also needs to be sent to Bundlr (either with the next block or independently), which complicates the sending mechanism.

Using delay function In this option, the sequencer network does not calculate the VRF data. The pseudorandom value passed to the contract is calculated as follows:

The computation of the delay function should be long enough that the proposer has no chance of computing it. Therefore, they cannot manipulate the block creation process based on the result. Note: The timeout for the proposer increases after each round in which block production fails. The delay function must take this into account.

The pseudorandom value would be calculated off-chain. We could create a service that calculates these values and provides them to the DRE nodes or SDK.

Using a hash chain with Arweave can also be considered.

➕ It does not complicate the sequencing process. ➖ The calculation of states for contracts that require pseudorandomness occurs with a certain delay due to VDF.

Using hashes of future blocks The pseudorandom value for a given block is calculated based on a sequence of hashes of blocks that follow the current block. This sequence must be long enough so that the proposers of those blocks have at least 1/3 of the votes. This ensures that not all the hashes were chosen by malicious nodes.

➕ A relatively simple solution. ➖ The length of the sequence will increase with the number of validators. Initially, it may only be a few blocks, but as the network grows, the delay (sequence length) will also increase.

szynwelski commented 1 year ago

Note: Example of implementation of VRF in Go: https://github.com/warp-contracts/sequencer/blob/test2/tagHelper/tags.go#L97

szynwelski commented 1 year ago

@ppedziwiatr @jakub-wojciechowski @janekolszak The above scenarios are open for discussion. My recommendation: delay function.

szynwelski commented 9 months ago

In addition to the above proposals, there are other approaches that allow for securely generating random values. Each of them has some drawback, for example, a complicated key generation process in the case of threshold signatures or weak performance in other solutions. See: Randomness in Blockchain Protocols for more information.

szynwelski commented 9 months ago

In the initial version of the sequencer, a simple method for generating random values (#71) was implemented as follows:

This is not a perfect solution as it gives the Proposer limited influence over the generated value. However, it is not worse than the current approach. The goal is to implement a completely unbiased solution in future version of the sequencer.

szynwelski commented 8 months ago

API for random numbers available in contracts: https://github.com/warp-contracts/warp/pull/474