mirror of
https://github.com/logos-blockchain/logos-blockchain-pocs.git
synced 2026-01-05 22:53:10 +00:00
pol: risc0 implementation of the PoL zk statemetn
This commit is contained in:
parent
c97499f6ac
commit
884232b2d3
@ -41,6 +41,15 @@ impl InputWitness {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn evolve_output(&self, balance_blinding: BalanceWitness) -> crate::OutputWitness {
|
||||||
|
crate::OutputWitness {
|
||||||
|
note: self.note,
|
||||||
|
balance_blinding,
|
||||||
|
nf_pk: self.nf_sk.commit(),
|
||||||
|
nonce: self.nonce.evolve(&self.nf_sk),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn nullifier(&self) -> Nullifier {
|
pub fn nullifier(&self) -> Nullifier {
|
||||||
Nullifier::new(self.nf_sk, self.nonce)
|
Nullifier::new(self.nf_sk, self.nonce)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -17,7 +17,7 @@ use sha2::{Digest, Sha256};
|
|||||||
|
|
||||||
// Maintained privately by note holder
|
// Maintained privately by note holder
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct NullifierSecret([u8; 16]);
|
pub struct NullifierSecret(pub [u8; 16]);
|
||||||
|
|
||||||
// Nullifier commitment is public information that
|
// Nullifier commitment is public information that
|
||||||
// can be provided to anyone wishing to transfer
|
// can be provided to anyone wishing to transfer
|
||||||
@ -29,7 +29,7 @@ pub struct NullifierCommitment([u8; 32]);
|
|||||||
// provide a nonce to differentiate notes controlled by the same
|
// provide a nonce to differentiate notes controlled by the same
|
||||||
// secret. Each note is assigned a unique nullifier nonce.
|
// secret. Each note is assigned a unique nullifier nonce.
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
pub struct NullifierNonce([u8; 16]);
|
pub struct NullifierNonce([u8; 32]);
|
||||||
|
|
||||||
// The nullifier attached to input notes to prove an input has not
|
// The nullifier attached to input notes to prove an input has not
|
||||||
// already been spent.
|
// already been spent.
|
||||||
@ -69,18 +69,28 @@ impl NullifierCommitment {
|
|||||||
|
|
||||||
impl NullifierNonce {
|
impl NullifierNonce {
|
||||||
pub fn random(mut rng: impl RngCore) -> Self {
|
pub fn random(mut rng: impl RngCore) -> Self {
|
||||||
let mut nonce = [0u8; 16];
|
let mut nonce = [0u8; 32];
|
||||||
rng.fill_bytes(&mut nonce);
|
rng.fill_bytes(&mut nonce);
|
||||||
Self(nonce)
|
Self(nonce)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_bytes(&self) -> &[u8; 16] {
|
pub fn as_bytes(&self) -> &[u8; 32] {
|
||||||
&self.0
|
&self.0
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_bytes(bytes: [u8; 16]) -> Self {
|
pub fn from_bytes(bytes: [u8; 32]) -> Self {
|
||||||
Self(bytes)
|
Self(bytes)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn evolve(&self, nf_sk: &NullifierSecret) -> Self {
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(b"NOMOS_COIN_EVOLVE");
|
||||||
|
hasher.update(&self.0);
|
||||||
|
hasher.update(nf_sk.0);
|
||||||
|
|
||||||
|
let nonce_bytes: [u8; 32] = hasher.finalize().into();
|
||||||
|
Self(nonce_bytes)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Nullifier {
|
impl Nullifier {
|
||||||
|
|||||||
2
proof_of_leadership/risc0/.gitignore
vendored
Normal file
2
proof_of_leadership/risc0/.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
Cargo.lock
|
||||||
|
target/
|
||||||
11
proof_of_leadership/risc0/Cargo.toml
Normal file
11
proof_of_leadership/risc0/Cargo.toml
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
[workspace]
|
||||||
|
resolver = "2"
|
||||||
|
members = [ "prover", "proof_statements", "risc0_proofs"]
|
||||||
|
|
||||||
|
# Always optimize; building and running the risc0_proofs takes much longer without optimization.
|
||||||
|
[profile.dev]
|
||||||
|
opt-level = 3
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
debug = 1
|
||||||
|
lto = true
|
||||||
10
proof_of_leadership/risc0/proof_statements/Cargo.toml
Normal file
10
proof_of_leadership/risc0/proof_statements/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "proof_statements"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cl = { path = "../../../goas/cl/cl" }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
crypto-bigint = { version = "0.5.5", features = ["serde"] }
|
||||||
|
sha2 = "0.10"
|
||||||
@ -0,0 +1,8 @@
|
|||||||
|
use cl::{Nullifier, PtxRoot};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct DeathConstraintPublic {
|
||||||
|
pub nf: Nullifier,
|
||||||
|
pub ptx_root: PtxRoot,
|
||||||
|
}
|
||||||
21
proof_of_leadership/risc0/proof_statements/src/input.rs
Normal file
21
proof_of_leadership/risc0/proof_statements/src/input.rs
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// for public inputs `nf` (nullifier), `root_cm` (root of merkle tree over commitment set) and `death_cm` (commitment to death constraint).
|
||||||
|
/// the prover has knowledge of `output = (note, nf_pk, nonce)`, `nf` and `path` s.t. that the following constraints hold
|
||||||
|
/// 0. nf_pk = hash(nf_sk)
|
||||||
|
/// 1. nf = hash(nonce||nf_sk)
|
||||||
|
/// 2. note_cm = output_commitment(output)
|
||||||
|
/// 3. verify_merkle_path(note_cm, root, path)
|
||||||
|
/// 4. death_cm = death_commitment(note.death_constraint)
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct InputPublic {
|
||||||
|
pub cm_root: [u8; 32],
|
||||||
|
pub input: cl::Input,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct InputPrivate {
|
||||||
|
pub input: cl::InputWitness,
|
||||||
|
pub cm_path: Vec<cl::merkle::PathNode>,
|
||||||
|
}
|
||||||
4
proof_of_leadership/risc0/proof_statements/src/lib.rs
Normal file
4
proof_of_leadership/risc0/proof_statements/src/lib.rs
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
pub mod death_constraint;
|
||||||
|
pub mod input;
|
||||||
|
pub mod ptx;
|
||||||
|
pub mod proof_of_leadership;
|
||||||
@ -0,0 +1,95 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use sha2::{Digest, Sha256};
|
||||||
|
use crypto_bigint::{U256, Encoding, CheckedMul, CheckedSub};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct LeaderPublic {
|
||||||
|
pub cm_root: [u8; 32],
|
||||||
|
pub epoch_nonce: [u8; 32],
|
||||||
|
pub slot: u64,
|
||||||
|
pub scaled_phi_approx: (U256, U256),
|
||||||
|
pub nullifier: cl::Nullifier,
|
||||||
|
pub updated_commitment: cl::NoteCommitment,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LeaderPublic {
|
||||||
|
pub fn new(
|
||||||
|
cm_root: [u8; 32],
|
||||||
|
epoch_nonce: [u8; 32],
|
||||||
|
slot: u64,
|
||||||
|
active_slot_coefficient: f64,
|
||||||
|
total_stake: u64,
|
||||||
|
nullifier: cl::Nullifier,
|
||||||
|
updated_commitment: cl::NoteCommitment
|
||||||
|
) -> Self
|
||||||
|
{
|
||||||
|
|
||||||
|
|
||||||
|
// TODO: check in sage that these precision adjustments are valid.
|
||||||
|
// also ensure that intermediate values going above the field
|
||||||
|
// order don't mess the final result of the evaluation.
|
||||||
|
let total_stake_big = U256::from_u64(total_stake);
|
||||||
|
let total_stake_sq_big = total_stake_big.checked_mul(&total_stake_big).unwrap();
|
||||||
|
let double_total_stake_sq_big = total_stake_sq_big.checked_mul(&U256::from_u64(2)).unwrap();
|
||||||
|
|
||||||
|
let precision_u64 = u64::MAX;
|
||||||
|
let precision_big = U256::from_u64(u64::MAX);
|
||||||
|
let precision_f64 = precision_u64 as f64;
|
||||||
|
let order: U256 = U256::MAX;
|
||||||
|
|
||||||
|
let order_div_precision = order.checked_div(&precision_big).unwrap();
|
||||||
|
let order_div_precision_sq = order_div_precision.checked_div(&precision_big).unwrap()
|
||||||
|
;
|
||||||
|
let neg_f_ln: U256 = U256::from_u64(((-f64::ln(1f64 - active_slot_coefficient)) * precision_f64) as u64);
|
||||||
|
let neg_f_ln_sq = neg_f_ln.checked_mul(&neg_f_ln).unwrap();
|
||||||
|
|
||||||
|
let neg_f_ln_order: U256 = order_div_precision.checked_mul(&neg_f_ln).unwrap();
|
||||||
|
let t0 = neg_f_ln_order.checked_div(&total_stake_big).unwrap();
|
||||||
|
let t1 = order_div_precision_sq.checked_mul(&neg_f_ln_sq).unwrap().checked_div(&double_total_stake_sq_big).unwrap();
|
||||||
|
|
||||||
|
Self {
|
||||||
|
cm_root,
|
||||||
|
epoch_nonce,
|
||||||
|
slot,
|
||||||
|
nullifier,
|
||||||
|
updated_commitment,
|
||||||
|
scaled_phi_approx: (t0, t1),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
pub fn check_winning(&self, input: &cl::InputWitness) -> bool {
|
||||||
|
// Lottery checks
|
||||||
|
let threshold = phi_approx(U256::from_u64(input.note.value), self.scaled_phi_approx);
|
||||||
|
let ticket = ticket(&input, self.epoch_nonce, self.slot);
|
||||||
|
ticket < threshold
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn phi_approx(stake: U256, approx: (U256, U256)) -> U256 {
|
||||||
|
// stake * (t0 - t1 * stake)
|
||||||
|
stake.checked_mul(&approx.0.checked_sub(&approx.1.checked_mul(&stake).unwrap()).unwrap()).unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ticket(input: &cl::InputWitness, epoch_nonce: [u8;32], slot: u64) -> U256 {
|
||||||
|
let mut hasher = Sha256::new();
|
||||||
|
hasher.update(b"NOMOS_LEAD");
|
||||||
|
hasher.update(epoch_nonce);
|
||||||
|
hasher.update(slot.to_be_bytes());
|
||||||
|
hasher.update(input.note_commitment().as_bytes());
|
||||||
|
hasher.update(input.nf_sk.0);
|
||||||
|
|
||||||
|
let ticket_bytes: [u8; 32] = hasher.finalize().into();
|
||||||
|
|
||||||
|
U256::from_be_bytes(ticket_bytes)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct LeaderPrivate {
|
||||||
|
pub input: cl::InputWitness,
|
||||||
|
pub input_cm_path: Vec<cl::merkle::PathNode>,
|
||||||
|
}
|
||||||
36
proof_of_leadership/risc0/proof_statements/src/ptx.rs
Normal file
36
proof_of_leadership/risc0/proof_statements/src/ptx.rs
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
use cl::{merkle, InputWitness, OutputWitness, PtxRoot};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
/// An input to a partial transaction
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct PartialTxInputPrivate {
|
||||||
|
pub input: InputWitness,
|
||||||
|
pub cm_path: Vec<merkle::PathNode>,
|
||||||
|
pub ptx_path: Vec<merkle::PathNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialTxInputPrivate {
|
||||||
|
pub fn ptx_root(&self) -> PtxRoot {
|
||||||
|
let leaf = merkle::leaf(&self.input.commit().to_bytes());
|
||||||
|
PtxRoot(merkle::path_root(leaf, &self.ptx_path))
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn cm_root(&self) -> [u8; 32] {
|
||||||
|
let leaf = merkle::leaf(self.input.note_commitment().as_bytes());
|
||||||
|
merkle::path_root(leaf, &self.cm_path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An output to a partial transaction
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||||
|
pub struct PartialTxOutputPrivate {
|
||||||
|
pub output: OutputWitness,
|
||||||
|
pub ptx_path: Vec<merkle::PathNode>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PartialTxOutputPrivate {
|
||||||
|
pub fn ptx_root(&self) -> PtxRoot {
|
||||||
|
let leaf = merkle::leaf(&self.output.commit().to_bytes());
|
||||||
|
PtxRoot(merkle::path_root(leaf, &self.ptx_path))
|
||||||
|
}
|
||||||
|
}
|
||||||
15
proof_of_leadership/risc0/prover/Cargo.toml
Normal file
15
proof_of_leadership/risc0/prover/Cargo.toml
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
[package]
|
||||||
|
name = "nomos_pol_prover"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
cl = { path = "../../../goas/cl/cl" }
|
||||||
|
proof_statements = { path = "../proof_statements" }
|
||||||
|
nomos_pol_risc0_proofs = { path = "../risc0_proofs" }
|
||||||
|
risc0-zkvm = { version = "1.0", features = ["prove", "metal"] }
|
||||||
|
risc0-groth16 = { version = "1.0" }
|
||||||
|
rand = "0.8.5"
|
||||||
|
rand_core = "0.6.0"
|
||||||
|
thiserror = "1.0.62"
|
||||||
|
curve25519-dalek = {version = "4.1", features = ["serde", "digest", "rand_core"]}
|
||||||
9
proof_of_leadership/risc0/prover/src/error.rs
Normal file
9
proof_of_leadership/risc0/prover/src/error.rs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
use thiserror::Error;
|
||||||
|
|
||||||
|
pub type Result<T> = core::result::Result<T, Error>;
|
||||||
|
|
||||||
|
#[derive(Error, Debug)]
|
||||||
|
pub enum Error {
|
||||||
|
#[error("risc0 failed to serde")]
|
||||||
|
Risc0Serde(#[from] risc0_zkvm::serde::Error),
|
||||||
|
}
|
||||||
182
proof_of_leadership/risc0/prover/src/leader.rs
Normal file
182
proof_of_leadership/risc0/prover/src/leader.rs
Normal file
@ -0,0 +1,182 @@
|
|||||||
|
use crate::error::Result;
|
||||||
|
|
||||||
|
use curve25519_dalek::Scalar;
|
||||||
|
|
||||||
|
use proof_statements::proof_of_leadership::{LeaderPrivate, LeaderPublic};
|
||||||
|
|
||||||
|
const MAX_NOTE_COMMS: usize = 2usize.pow(8);
|
||||||
|
|
||||||
|
|
||||||
|
pub struct ProvedLeader {
|
||||||
|
pub leader: LeaderPublic,
|
||||||
|
pub risc0_receipt: risc0_zkvm::Receipt,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
impl ProvedLeader {
|
||||||
|
pub fn prove(input: &cl::InputWitness, epoch_nonce: [u8;32], slot: u64, active_slot_coefficient: f64, total_stake: u64, note_commitments: &[cl::NoteCommitment]) -> Self {
|
||||||
|
let note_cm = input.note_commitment();
|
||||||
|
let cm_leaves = note_commitment_leaves(note_commitments);
|
||||||
|
let cm_idx = note_commitments
|
||||||
|
.iter()
|
||||||
|
.position(|c| c == ¬e_cm)
|
||||||
|
.unwrap();
|
||||||
|
let note_cm_path = cl::merkle::path(cm_leaves, cm_idx);
|
||||||
|
let cm_root = cl::merkle::root(cm_leaves);
|
||||||
|
|
||||||
|
let leader_private = LeaderPrivate {
|
||||||
|
input: *input,
|
||||||
|
input_cm_path: note_cm_path,
|
||||||
|
};
|
||||||
|
|
||||||
|
let leader_public = LeaderPublic::new(
|
||||||
|
cm_root,
|
||||||
|
epoch_nonce,
|
||||||
|
slot,
|
||||||
|
active_slot_coefficient,
|
||||||
|
total_stake,
|
||||||
|
input.nullifier(),
|
||||||
|
input.evolve_output(cl::BalanceWitness::new(Scalar::ZERO)).commit_note(),
|
||||||
|
);
|
||||||
|
|
||||||
|
let env = risc0_zkvm::ExecutorEnv::builder()
|
||||||
|
.write(&leader_public)
|
||||||
|
.unwrap()
|
||||||
|
.write(&leader_private)
|
||||||
|
.unwrap()
|
||||||
|
.build()
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Obtain the default prover.
|
||||||
|
let prover = risc0_zkvm::default_prover();
|
||||||
|
|
||||||
|
let start_t = std::time::Instant::now();
|
||||||
|
|
||||||
|
// Proof information by proving the specified ELF binary.
|
||||||
|
// This struct contains the receipt along with statistics about execution of the guest
|
||||||
|
let opts = risc0_zkvm::ProverOpts::succinct();
|
||||||
|
let prove_info = prover
|
||||||
|
.prove_with_opts(env, nomos_pol_risc0_proofs::PROOF_OF_LEADERSHIP_ELF, &opts)
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
println!(
|
||||||
|
"STARK prover time: {:.2?}, total_cycles: {}",
|
||||||
|
start_t.elapsed(),
|
||||||
|
prove_info.stats.total_cycles
|
||||||
|
);
|
||||||
|
// extract the receipt.
|
||||||
|
let receipt = prove_info.receipt;
|
||||||
|
|
||||||
|
Self {
|
||||||
|
leader: leader_public,
|
||||||
|
risc0_receipt: receipt,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn public(&self) -> Result<LeaderPublic> {
|
||||||
|
Ok(self.risc0_receipt.journal.decode()?)
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn verify(&self) -> bool {
|
||||||
|
let Ok(proved_public_inputs) = self.public() else {
|
||||||
|
return false;
|
||||||
|
};
|
||||||
|
|
||||||
|
self.leader == proved_public_inputs
|
||||||
|
&& self
|
||||||
|
.risc0_receipt
|
||||||
|
.verify(nomos_pol_risc0_proofs::PROOF_OF_LEADERSHIP_ID)
|
||||||
|
.is_ok()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
fn note_commitment_leaves(note_commitments: &[cl::NoteCommitment]) -> [[u8; 32]; MAX_NOTE_COMMS] {
|
||||||
|
let note_comm_bytes = Vec::from_iter(note_commitments.iter().map(|c| c.as_bytes().to_vec()));
|
||||||
|
let cm_leaves = cl::merkle::padded_leaves::<MAX_NOTE_COMMS>(¬e_comm_bytes);
|
||||||
|
cm_leaves
|
||||||
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod test {
|
||||||
|
use rand::thread_rng;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_leader_prover() {
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
|
let input = cl::InputWitness {
|
||||||
|
note: cl::NoteWitness::basic(32, "NMO"),
|
||||||
|
balance_blinding: cl::BalanceWitness::random(&mut rng),
|
||||||
|
nf_sk: cl::NullifierSecret::random(&mut rng),
|
||||||
|
nonce: cl::NullifierNonce::random(&mut rng),
|
||||||
|
};
|
||||||
|
|
||||||
|
let notes = vec![input.note_commitment()];
|
||||||
|
let epoch_nonce = [0u8; 32];
|
||||||
|
let slot = 0;
|
||||||
|
let active_slot_coefficient = 0.05;
|
||||||
|
let total_stake = 1000;
|
||||||
|
|
||||||
|
let mut expected_public_inputs = LeaderPublic::new(
|
||||||
|
cl::merkle::root(note_commitment_leaves(¬es)),
|
||||||
|
epoch_nonce,
|
||||||
|
slot,
|
||||||
|
active_slot_coefficient,
|
||||||
|
total_stake,
|
||||||
|
input.nullifier(),
|
||||||
|
input.evolve_output(cl::BalanceWitness::new(Scalar::ZERO)).commit_note(),
|
||||||
|
);
|
||||||
|
|
||||||
|
while !expected_public_inputs.check_winning(&input) {
|
||||||
|
expected_public_inputs.slot += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
println!("slot={}", expected_public_inputs.slot);
|
||||||
|
|
||||||
|
let proved_leader = ProvedLeader::prove(&input, expected_public_inputs.epoch_nonce, expected_public_inputs.slot, active_slot_coefficient, total_stake, ¬es);
|
||||||
|
|
||||||
|
|
||||||
|
assert_eq!(proved_leader.leader, expected_public_inputs);
|
||||||
|
assert!(proved_leader.verify());
|
||||||
|
|
||||||
|
// let wrong_public_inputs = [
|
||||||
|
// InputPublic {
|
||||||
|
// cm_root: cl::merkle::root([cl::merkle::leaf(b"bad_root")]),
|
||||||
|
// ..expected_public_inputs
|
||||||
|
// },
|
||||||
|
// InputPublic {
|
||||||
|
// input: cl::Input {
|
||||||
|
// nullifier: cl::Nullifier::new(
|
||||||
|
// cl::NullifierSecret::random(&mut rng),
|
||||||
|
// cl::NullifierNonce::random(&mut rng),
|
||||||
|
// ),
|
||||||
|
// ..expected_public_inputs.input
|
||||||
|
// },
|
||||||
|
// ..expected_public_inputs
|
||||||
|
// },
|
||||||
|
// InputPublic {
|
||||||
|
// input: cl::Input {
|
||||||
|
// death_cm: cl::note::death_commitment(b"wrong death vk"),
|
||||||
|
// ..expected_public_inputs.input
|
||||||
|
// },
|
||||||
|
// ..expected_public_inputs
|
||||||
|
// },
|
||||||
|
// InputPublic {
|
||||||
|
// input: cl::Input {
|
||||||
|
// balance: cl::BalanceWitness::random(&mut rng)
|
||||||
|
// .commit(&cl::NoteWitness::basic(32, "NMO")),
|
||||||
|
// ..expected_public_inputs.input
|
||||||
|
// },
|
||||||
|
// ..expected_public_inputs
|
||||||
|
// },
|
||||||
|
// ];
|
||||||
|
|
||||||
|
// for wrong_input in wrong_public_inputs {
|
||||||
|
// proved_input.input = wrong_input;
|
||||||
|
// assert!(!proved_input.verify());
|
||||||
|
// }
|
||||||
|
}
|
||||||
|
}
|
||||||
2
proof_of_leadership/risc0/prover/src/lib.rs
Normal file
2
proof_of_leadership/risc0/prover/src/lib.rs
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
pub mod error;
|
||||||
|
pub mod leader;
|
||||||
10
proof_of_leadership/risc0/risc0_proofs/Cargo.toml
Normal file
10
proof_of_leadership/risc0/risc0_proofs/Cargo.toml
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
[package]
|
||||||
|
name = "nomos_pol_risc0_proofs"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
risc0-build = { version = "1.0" }
|
||||||
|
|
||||||
|
[package.metadata.risc0]
|
||||||
|
methods = ["proof_of_leadership"]
|
||||||
3
proof_of_leadership/risc0/risc0_proofs/build.rs
Normal file
3
proof_of_leadership/risc0/risc0_proofs/build.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
fn main() {
|
||||||
|
risc0_build::embed_methods();
|
||||||
|
}
|
||||||
@ -0,0 +1,23 @@
|
|||||||
|
[package]
|
||||||
|
name = "proof_of_leadership"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[workspace]
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
risc0-zkvm = { version = "1.0", default-features = false, features = ['std'] }
|
||||||
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
cl = { path = "../../../../goas/cl/cl" }
|
||||||
|
proof_statements = { path = "../../proof_statements" }
|
||||||
|
curve25519-dalek = {version = "4.1", features = ["serde", "digest", "rand_core"]}
|
||||||
|
sha2 = "0.10"
|
||||||
|
crypto-bigint = "0.5.5"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
[patch.crates-io]
|
||||||
|
# add RISC Zero accelerator support for all downstream usages of the following crates.
|
||||||
|
sha2 = { git = "https://github.com/risc0/RustCrypto-hashes", tag = "sha2-v0.10.8-risczero.0" }
|
||||||
|
crypto-bigint = { git = "https://github.com/risc0/RustCrypto-crypto-bigint", tag = "v0.5.5-risczero.0" }
|
||||||
|
curve25519-dalek = { git = "https://github.com/risc0/curve25519-dalek", tag = "curve25519-4.1.2-risczero.0" }
|
||||||
@ -0,0 +1,34 @@
|
|||||||
|
/// Proof of Leadership
|
||||||
|
use cl::merkle;
|
||||||
|
use curve25519_dalek::Scalar;
|
||||||
|
use proof_statements::proof_of_leadership::{LeaderPrivate, LeaderPublic};
|
||||||
|
use risc0_zkvm::guest::env;
|
||||||
|
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
let public_inputs: LeaderPublic = env::read();
|
||||||
|
|
||||||
|
let LeaderPrivate {
|
||||||
|
input,
|
||||||
|
input_cm_path,
|
||||||
|
} = env::read();
|
||||||
|
|
||||||
|
// Lottery checks
|
||||||
|
assert!(public_inputs.check_winning(&input));
|
||||||
|
|
||||||
|
|
||||||
|
// Ensure note is valid
|
||||||
|
let note_cm = input.note_commitment();
|
||||||
|
let note_cm_leaf = merkle::leaf(note_cm.as_bytes());
|
||||||
|
let note_cm_root = merkle::path_root(note_cm_leaf, &input_cm_path);
|
||||||
|
assert_eq!(note_cm_root, public_inputs.cm_root);
|
||||||
|
|
||||||
|
|
||||||
|
// Public input constraints
|
||||||
|
assert_eq!(input.nullifier(), public_inputs.nullifier);
|
||||||
|
|
||||||
|
let evolved_output = input.evolve_output(cl::BalanceWitness::new(Scalar::ZERO));
|
||||||
|
assert_eq!(evolved_output.commit_note(), public_inputs.updated_commitment);
|
||||||
|
|
||||||
|
env::commit(&public_inputs);
|
||||||
|
}
|
||||||
1
proof_of_leadership/risc0/risc0_proofs/src/lib.rs
Normal file
1
proof_of_leadership/risc0/risc0_proofs/src/lib.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
include!(concat!(env!("OUT_DIR"), "/methods.rs"));
|
||||||
Loading…
x
Reference in New Issue
Block a user