Skip to content

Commit

Permalink
ran prettier:fix
Browse files Browse the repository at this point in the history
  • Loading branch information
adpthegreat committed Oct 23, 2024
1 parent 42555e8 commit abe3be5
Showing 1 changed file with 55 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,10 @@ description: "Use proper cryptographic randomness in your onchain programs."

- Attempts at generating randomness within your program are likely to be
guessable by users given there's no true randomness onchain.
- Verifiable Random Functions (VRFs) allow developers to
incorporate securely generated random numbers in their onchain programs.
- A VRF is a public-key pseudorandom function that proves its
outputs were calculated correctly.
- Verifiable Random Functions (VRFs) allow developers to incorporate securely
generated random numbers in their onchain programs.
- A VRF is a public-key pseudorandom function that proves its outputs were
calculated correctly.
- Switchboard offers a developer-friendly VRF for the Solana ecosystem.

## Lesson
Expand All @@ -33,8 +33,8 @@ in a decentralized fashion.

Before we dive into how random numbers can be generated for a blockchain, we
must first understand how they are generated on traditional computer systems.
There are two types of random numbers: _true random_ and _pseudorandom_.
The difference between the two lies in how the numbers are generated.
There are two types of random numbers: _true random_ and _pseudorandom_. The
difference between the two lies in how the numbers are generated.

Computers can acquire _true random_ numbers by taking some type of physical
measurement of the outside world as entropy. These measurements take advantage
Expand Down Expand Up @@ -65,16 +65,15 @@ more. So we'll have to look outside of the blockchain for randomness with VRFs.
### What is Verifiable Randomness?

A Verifiable Random Function (VRF) is a public-key pseudorandom function that
provides proof that its outputs were calculated correctly. This means we can
use a cryptographic keypair to generate a random number with a proof, which can
then be validated by anyone to ensure the value was calculated correctly without
the possibility of leaking the producer's secret key. Once validated, the random
provides proof that its outputs were calculated correctly. This means we can use
a cryptographic keypair to generate a random number with a proof, which can then
be validated by anyone to ensure the value was calculated correctly without the
possibility of leaking the producer's secret key. Once validated, the random
value is stored onchain in an account.

VRFs are a crucial component for achieving verifiable and unpredictable
randomness on a blockchain, addressing some of the shortcomings of traditional
PRNGs and the challenges of achieving true randomness in a decentralized
system.
PRNGs and the challenges of achieving true randomness in a decentralized system.

There are three key properties of a VRF:

Expand Down Expand Up @@ -135,16 +134,17 @@ and consuming randomness from Switchboard looks like this:
6. Once VRF proof is verified, the Switchboard program will invoke the
`callback` that was passed in as the callback in the initial request with the
pseudorandom number returned from the Oracle.
7. The program consumes the random number and can execute business logic with it!
7. The program consumes the random number and can execute business logic with
it!

There are a lot of steps here, but don't worry, we'll be going through each step
of the process in detail.

First, there are a couple of accounts that we will have to create to
request randomness, specifically the `authority` and `vrf` accounts. The
`authority` account is a PDA derived from our program that is requesting
randomness. So the PDA we create will have our seeds for our needs. For
now, we'll simply set them at `VRFAUTH`.
First, there are a couple of accounts that we will have to create to request
randomness, specifically the `authority` and `vrf` accounts. The `authority`
account is a PDA derived from our program that is requesting randomness. So the
PDA we create will have our seeds for our needs. For now, we'll simply set them
at `VRFAUTH`.

```typescript
// derive PDA
Expand Down Expand Up @@ -188,15 +188,16 @@ pub struct VrfAccountData {
```

Some important fields on this account are `authority`, `oracle_queue`, and
`callback`. The `authority` should be a PDA of the program that can
request randomness on this `vrf` account. That way, only that program can
provide the signature needed for the vrf request. The `oracle_queue` field
allows you to specify which specific oracle queue you’d like to service the vrf
requests made with this account. If you aren’t familiar with oracle queues on
Switchboard, check the
`callback`. The `authority` should be a PDA of the program that can request
randomness on this `vrf` account. That way, only that program can provide the
signature needed for the vrf request. The `oracle_queue` field allows you to
specify which specific oracle queue you’d like to service the vrf requests made
with this account. If you aren’t familiar with oracle queues on Switchboard,
check the
[Oracles lesson in the Connecting to Offchain Data course](/content/courses/connecting-to-offchain-data/oracles)!
Lastly, the `callback` field is where you define the callback instruction the
Switchboard program should be invoked once the randomness result has been verified.
Switchboard program should be invoked once the randomness result has been
verified.

The `callback` field is of type
`[CallbackZC](https://github.com/switchboard-xyz/solana-sdk/blob/9dc3df8a5abe261e23d46d14f9e80a7032bb346c/rust/switchboard-solana/src/oracle_program/accounts/ecvrf.rs#L25)`.
Expand Down Expand Up @@ -413,9 +414,9 @@ pub fn handler(ctx: Context<ConsumeRandomness>) -> Result <()> {
}
```

Now you have randomness! Hooray! But there is one last thing we have not discussed
yet and that's how the randomness is returned. Switchboard, gives you your
randomness calling
Now you have randomness! Hooray! But there is one last thing we have not
discussed yet and that's how the randomness is returned. Switchboard, gives you
your randomness calling
[`get_result()`](https://github.com/switchboard-xyz/solana-sdk/blob/9dc3df8a5abe261e23d46d14f9e80a7032bb346c/rust/switchboard-solana/src/oracle_program/accounts/vrf.rs#L122).
This method returns the `current_round.result` field of the `vrf` account
SwitchboardDecimal format, which is just a buffer of 32 random
Expand Down Expand Up @@ -450,13 +451,13 @@ is provided for you in
[the main branch of the lab Github repository](https://github.com/solana-developers/burry-escrow).
[the main branch of the lab Github repository](https://github.com/solana-developers/burry-escrow).

The repo contains a "Michael Burry" escrow program. This program
allows a user to lock up some SOL funds in escrow that cannot be withdrawn
until SOL has reached a predefined price in USD chosen by the user. We will be
adding VRF functionality to this program to allow the user to "Get out of jail"
by rolling doubles. Our demo today will allow the user to roll two virtual dice,
if they roll doubles (the two dice match), the user can withdraw their funds
from escrow regardless of the SOL price.
The repo contains a "Michael Burry" escrow program. This program allows a user
to lock up some SOL funds in escrow that cannot be withdrawn until SOL has
reached a predefined price in USD chosen by the user. We will be adding VRF
functionality to this program to allow the user to "Get out of jail" by rolling
doubles. Our demo today will allow the user to roll two virtual dice, if they
roll doubles (the two dice match), the user can withdraw their funds from escrow
regardless of the SOL price.

### 1. Program Setup

Expand Down Expand Up @@ -574,11 +575,11 @@ hold the state of our dice rolls. It will have the following fields:
will create this before we call `VrfClient`'s initialization function.
- `escrow` - Public key of our burry escrow account.

We will also make the `VrfClient` context a `zero_copy` struct. This
means that we will initialize it with `load_init()` and pass it into accounts
with `AccountLoader`. We do this because VRF functions are very account
intensive and we need to be mindful of the stack. If you'd like to learn more
about `zero_copy`, take a look at our
We will also make the `VrfClient` context a `zero_copy` struct. This means that
we will initialize it with `load_init()` and pass it into accounts with
`AccountLoader`. We do this because VRF functions are very account intensive and
we need to be mindful of the stack. If you'd like to learn more about
`zero_copy`, take a look at our
[Program Architecture lesson](/developers/courses/program-optimization/program-architecture).

```rust
Expand All @@ -599,7 +600,8 @@ pub struct VrfClient {
}
```

Lastly, we are going to add the `VRF_STATE_SEED` to the PDA of our VRF Client account.
Lastly, we are going to add the `VRF_STATE_SEED` to the PDA of our VRF Client
account.

```rust
pub const VRF_STATE_SEED: &[u8] = b"VRFCLIENT";
Expand Down Expand Up @@ -938,11 +940,11 @@ pub struct RequestRandomnessParams {
}
```

Now, we can focus on implementing the logic of this instruction. The logic should collect all
the necessary accounts needed and pass them to
Now, we can focus on implementing the logic of this instruction. The logic
should collect all the necessary accounts needed and pass them to
`[VrfRequestRandomness](https://github.com/switchboard-xyz/solana-sdk/blob/fbef37e4a78cbd8b8b6346fcb96af1e20204b861/rust/switchboard-solana/src/oracle_program/instructions/vrf_request_randomness.rs#L8)`,
which is a well designed struct from Switchboard. After that we'll sign the request and
send it on it's way.
which is a well designed struct from Switchboard. After that we'll sign the
request and send it on it's way.

```rust
pub fn get_out_of_jail_handler(ctx: Context<RequestRandomness>, params: RequestRandomnessParams) -> Result <()> {
Expand Down Expand Up @@ -1097,13 +1099,14 @@ Now it’s time to use the random result. Since we're working with two dice we
only need the first two bytes of the buffer. To convert these random values into
“dice rolls”, we use modular arithmetic. For anyone not familiar with modular
arithmetic,
[this Wikipedia article](https://en.wikipedia.org/wiki/Modular_arithmetic) provides a helpful introduction. In
modular arithmetic, numbers "wrap around" when they reach a given fixed given quantity.
This given quantity is known as the modulus to leave as the remainder. In our case, the
modulus is the `dice_type` stored on the `vrf_state` account. We hard-coded this
to 6 when the account was initialized to represent a 6-sided die. When we use
`dice_type`, or 6, as the modulus, our result will be a number between 0 and 5. We then add
one to shift tha range, making the possible outcomes 1-6.
[this Wikipedia article](https://en.wikipedia.org/wiki/Modular_arithmetic)
provides a helpful introduction. In modular arithmetic, numbers "wrap around"
when they reach a given fixed given quantity. This given quantity is known as
the modulus to leave as the remainder. In our case, the modulus is the
`dice_type` stored on the `vrf_state` account. We hard-coded this to 6 when the
account was initialized to represent a 6-sided die. When we use `dice_type`, or
6, as the modulus, our result will be a number between 0 and 5. We then add one
to shift tha range, making the possible outcomes 1-6.

```rust
pub fn consume_randomness_handler(ctx: Context<ConsumeRandomness>) -> Result <()> {
Expand Down

0 comments on commit abe3be5

Please sign in to comment.