An open API service indexing awesome lists of open source software.

https://github.com/dojoengine/stark-vrf

A VRF implementation using Stark curve and Poseidon hash.
https://github.com/dojoengine/stark-vrf

Last synced: 8 months ago
JSON representation

A VRF implementation using Stark curve and Poseidon hash.

Awesome Lists containing this project

README

          

# Stark VRF

This repository implements the VRF spec (https://datatracker.ietf.org/doc/html/rfc9381)
using Stark curve and Poseidon hash for efficient verification on Starknet.

This repository contains two parts:
* VRF prover and verifier implemented in Rust. It can be used not only to generate a VRF
proof but also supplements all necessary hints for cheap verification in Cairo.
* An efficient Cairo verifier.

## Usage

### Proof generation

Proofs can be generated by using the provided `stark-vrf` crate.

```rust
use stark_vrf::{Error, generate_public_key, Proof, ScalarValue, StarkVRF};

#[test]
fn it_generates_proof() -> Result {
let secret_key = ScalarValue!("190");
let public_key = generate_public_key(secret_key);

let seed = &[ScalarValue!("42")];
let ecvrf = StarkVRF::new(public_key).unwrap();
ecvrf.prove(&secret_key, seed)
}
```

### Hints for fast verification

VRF proof verification requires calculating a square root on field elements which is very
inefficient when implemented in Cairo. Instead, Rust code can generate a "sqrt_ratio_hint"
that makes verification much cheaper.

```rust
let sqrt_ratio_hint = ecvrf.hash_to_sqrt_ratio_hint(seed);
```

### Proof verification, random output generation

For completeness and testing, Rust also provides a way to verify proofs generated by itself.

```rust
ecvrf.verify(&proof, seed).expect("proof correct");
let random_word = ecvrf.proof_to_hash(&proof).unwrap();
```

### Proof verification in Cairo

This repository also provides a "stark_vrf" Scarb package for easy VRF proof verification in Cairo.

```rust
pub use stark_vrf::ecvrf::{Point, Proof, ECVRF, ECVRFImpl};

// sample output obtained from Rust code
fn proof_from_oracle() -> Proof {
Proof {
gamma: Point {
x: 1506339363762384048749124975867331702319430609263271304275332020910807468800,
y: 36259598506905210600179635686591002688831785399437338349196739602416217657
},
c: 2613903846701008054856365693011070443633034612733309583190565217827378733393,
s: 1867682679224997956048283066055885717352683300581532690215097247223135564277,
sqrt_ratio_hint: 2921944847064913001096235045564630676660517332237551444115611698074403533689,
}
}

#[test]
fn ecvrf_verify() {
// verifiers must ensure the public key hasn't changed
let pk = Point {
x: 2465182048640915825114623967805639036884813714770257338089158027381626459289,
y: 3038635738014387716559859267483610492356329532552881764846792983975787300333
};
let proof = proof_from_oracle();
let ecvrf = ECVRFImpl::new(pk);
let mut seed = ArrayTrait::new();
seed.append(42);

// 👇 proof verification
let actual_beta = ecvrf.verify(proof, seed.span()).unwrap();

let expected_beta = 1749760720107131022781690892024891617311129198096286233628341005792224087740;
assert_eq!(expected_beta, actual_beta);
}
```