| 12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152 |
- ---
- title: Protocol Design
- description: Understanding how Pyth Entropy generates secure random numbers
- ---
- The Entropy protocol implements a secure 2-party random number generation procedure. The protocol
- is an extension of a simple commit/reveal protocol. The original version has the following steps:
- 1. Two parties A and B each randomly sample secret contributions to the random number, $$(x_A)$$ and $$(x_B)$$.
- 2. A commits to their number by sharing $$(h_A) = hash(x_A).$$
- 3. B reveals $x_B$
- 4. A reveals $x_A$
- 5. B verifies that $$hash(x_{A}) == h_A$$
- 6. The random number $$r = hash(x_A, x_B)$$
- This protocol has the property that the result is random as long as either A or B are honest.
- Honesty means that (1) they draw their value at random, and (2) for A, they keep $$(x_A)$$ a secret until
- step 4. Thus, neither party needs to trust the other -- as long as they are themselves honest, they can
- ensure that the result $$(r)$$ is random.
- Entropy implements a version of this protocol that is optimized for on-chain usage. The
- key difference is that one of the participants (the provider) commits to a sequence of random numbers
- up-front using a hash chain. Users of the protocol then simply grab the next random number in the sequence.
- **Setup**: The provider $$P$$ computes a sequence of $$N$$ random numbers, $$x_i$$ for $$0 \leq i \leq N-1$$:
- - $$x_{N-1} = random()$$
- - $$x_i = hash(x_{i + 1})$$
- The provider commits to $$x_0$$ by posting it to the Entropy contract.
- Each random number in the sequence can then be verified against the previous one in the sequence by hashing it, i.e., $$hash(x_i) = x_{i - 1}$$
- **Request**: To produce a random number, the following steps occur.
- 1. The user randomly samples their contribution $$(x_U)$$ and submits it to the contract.
- (Users may also run this step using an on-chain PRNG if they trust the validator to not collude with the provider.)
- 2. The contract remembers $$(x_U)$$ and assigns it an incrementing sequence number $$(i)$$, representing which
- of the provider's random numbers the user will receive.
- 3. After sufficient block confirmations, the provider submits a transaction to the contract revealing their contribution $$(x_i)$$ to the contract.
- 4. The contract verifies $$hash(x_i) == x_{i-1}$$ to prove that $$(x_i)$$ is the $$(i)$$'th random number.
- The contract stores $$(x_i)$$ as the $$(i)$$'th random number to reuse for future verifications.
- 5. If the condition above is satisfied, the random number $$(r) = hash(x_i, x_U)$$.
- 6. The contract submits a callback to the calling contract with the random number $$(r)$$.
- This flow is secure as long as several trust assumptions hold:
- - Providers are trusted to reveal their random number $$(x_i)$$ regardless of what the final result $$(r)$$ is. Providers can compute $$(r)$$ off-chain before they reveal $$(x_i)$$, which permits a censorship attack.
- - Providers are trusted not to front-run user transactions (via the mempool or colluding with the validator). Providers who observe user transactions can manipulate the result by inserting additional reuests or rotating their commitment.
- - Providers are trusted not to keep their hash chain a secret. Anyone with the hash chain can predict the result of a randomness request before it is requested,
- and therefore manipulate the result. This applies both to users of the protocol as well as blockchain validators who can use this information to manipulate the on-chain PRNG or reorder user transactions.
- The code of default deployed provider can be found [here](https://github.com/pyth-network/pyth-crosschain/tree/7bccde484f01c19844b7105d63df207a24018957/apps/fortuna).
|