mirror of
https://github.com/logos-storage/plonky2.git
synced 2026-01-05 23:33:07 +00:00
Added PoW
This commit is contained in:
parent
4d31f5e37b
commit
a1023e0ca6
78
src/fri.rs
78
src/fri.rs
@ -1,11 +1,11 @@
|
|||||||
use crate::field::fft::fft;
|
use crate::field::fft::fft;
|
||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::hash::{compress, hash_n_to_hash};
|
use crate::hash::hash_n_to_1;
|
||||||
use crate::merkle_proofs::verify_merkle_proof;
|
use crate::merkle_proofs::verify_merkle_proof;
|
||||||
use crate::merkle_tree::MerkleTree;
|
use crate::merkle_tree::MerkleTree;
|
||||||
use crate::plonk_challenger::Challenger;
|
use crate::plonk_challenger::Challenger;
|
||||||
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
use crate::polynomial::polynomial::{PolynomialCoeffs, PolynomialValues};
|
||||||
use crate::proof::{FriEvaluations, FriMerkleProofs, FriProof, FriQueryRound, Hash};
|
use crate::proof::{FriEvaluations, FriMerkleProofs, FriProof, FriQueryRound};
|
||||||
use crate::util::log2_strict;
|
use crate::util::log2_strict;
|
||||||
use anyhow::{ensure, Result};
|
use anyhow::{ensure, Result};
|
||||||
|
|
||||||
@ -14,7 +14,7 @@ use anyhow::{ensure, Result};
|
|||||||
const EPSILON: f64 = 0.01;
|
const EPSILON: f64 = 0.01;
|
||||||
|
|
||||||
struct FriConfig {
|
struct FriConfig {
|
||||||
proof_of_work_bits: usize,
|
proof_of_work_bits: u32,
|
||||||
|
|
||||||
/// The arity of each FRI reduction step, expressed (i.e. the log2 of the actual arity).
|
/// The arity of each FRI reduction step, expressed (i.e. the log2 of the actual arity).
|
||||||
/// For example, `[3, 2, 1]` would describe a FRI reduction tree with 8-to-1 reduction, then
|
/// For example, `[3, 2, 1]` would describe a FRI reduction tree with 8-to-1 reduction, then
|
||||||
@ -67,17 +67,41 @@ fn fri_proof<F: Field>(
|
|||||||
let n = polynomial_values.values.len();
|
let n = polynomial_values.values.len();
|
||||||
assert_eq!(polynomial_coeffs.coeffs.len(), n);
|
assert_eq!(polynomial_coeffs.coeffs.len(), n);
|
||||||
|
|
||||||
|
// Commit phase
|
||||||
|
let (trees, final_coeffs) =
|
||||||
|
fri_committed_trees(polynomial_coeffs, polynomial_values, challenger, config);
|
||||||
|
|
||||||
|
let current_hash = challenger.get_challenge();
|
||||||
|
let pow_witness = fri_proof_of_work(current_hash, config);
|
||||||
|
|
||||||
|
// Query phase
|
||||||
|
let query_round_proofs = fri_query_rounds(&trees, challenger, n, config);
|
||||||
|
|
||||||
|
FriProof {
|
||||||
|
commit_phase_merkle_roots: trees.iter().map(|t| t.root).collect(),
|
||||||
|
// TODO: Fix this
|
||||||
|
initial_merkle_proofs: vec![],
|
||||||
|
query_round_proofs,
|
||||||
|
final_poly: final_coeffs,
|
||||||
|
pow_witness,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fri_committed_trees<F: Field>(
|
||||||
|
polynomial_coeffs: &PolynomialCoeffs<F>,
|
||||||
|
polynomial_values: &PolynomialValues<F>,
|
||||||
|
challenger: &mut Challenger<F>,
|
||||||
|
config: &FriConfig,
|
||||||
|
) -> (Vec<MerkleTree<F>>, PolynomialCoeffs<F>) {
|
||||||
let mut trees = vec![MerkleTree::new(
|
let mut trees = vec![MerkleTree::new(
|
||||||
polynomial_values.values.iter().map(|&v| vec![v]).collect(),
|
polynomial_values.values.iter().map(|&v| vec![v]).collect(),
|
||||||
true,
|
true,
|
||||||
)];
|
)];
|
||||||
let mut root = trees[0].root;
|
|
||||||
let mut coeffs = polynomial_coeffs.clone();
|
let mut coeffs = polynomial_coeffs.clone();
|
||||||
let mut values;
|
let mut values;
|
||||||
|
|
||||||
challenger.observe_hash(&root);
|
challenger.observe_hash(&trees[0].root);
|
||||||
|
|
||||||
// Commit phase
|
|
||||||
for _ in 0..config.reduction_count {
|
for _ in 0..config.reduction_count {
|
||||||
let beta = challenger.get_challenge();
|
let beta = challenger.get_challenge();
|
||||||
// P(x) = P_0(x^2) + xP_1(x^2) becomes P_0(x) + beta*P_1(x)
|
// P(x) = P_0(x^2) + xP_1(x^2) becomes P_0(x) + beta*P_1(x)
|
||||||
@ -94,8 +118,27 @@ fn fri_proof<F: Field>(
|
|||||||
challenger.observe_hash(&tree.root);
|
challenger.observe_hash(&tree.root);
|
||||||
trees.push(tree);
|
trees.push(tree);
|
||||||
}
|
}
|
||||||
|
(trees, coeffs)
|
||||||
|
}
|
||||||
|
|
||||||
// Query phase
|
fn fri_proof_of_work<F: Field>(current_hash: F, config: &FriConfig) -> F {
|
||||||
|
(0u64..)
|
||||||
|
.find(|&i| {
|
||||||
|
hash_n_to_1(vec![current_hash, F::from_canonical_u64(i)], false)
|
||||||
|
.to_canonical_u64()
|
||||||
|
.leading_zeros()
|
||||||
|
>= config.proof_of_work_bits
|
||||||
|
})
|
||||||
|
.map(F::from_canonical_u64)
|
||||||
|
.expect("Proof of work failed.")
|
||||||
|
}
|
||||||
|
|
||||||
|
fn fri_query_rounds<F: Field>(
|
||||||
|
trees: &[MerkleTree<F>],
|
||||||
|
challenger: &mut Challenger<F>,
|
||||||
|
n: usize,
|
||||||
|
config: &FriConfig,
|
||||||
|
) -> Vec<FriQueryRound<F>> {
|
||||||
let mut query_round_proofs = Vec::new();
|
let mut query_round_proofs = Vec::new();
|
||||||
for _ in 0..config.num_query_rounds {
|
for _ in 0..config.num_query_rounds {
|
||||||
let mut merkle_proofs = FriMerkleProofs { proofs: Vec::new() };
|
let mut merkle_proofs = FriMerkleProofs { proofs: Vec::new() };
|
||||||
@ -131,13 +174,7 @@ fn fri_proof<F: Field>(
|
|||||||
merkle_proofs,
|
merkle_proofs,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
query_round_proofs
|
||||||
FriProof {
|
|
||||||
commit_phase_merkle_roots: trees.iter().map(|t| t.root).collect(),
|
|
||||||
initial_merkle_proofs: vec![],
|
|
||||||
query_round_proofs,
|
|
||||||
final_poly: coeffs,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Computes P'(x^2) from P_even(x) and P_odd(x), where P' is the FRI reduced polynomial,
|
/// Computes P'(x^2) from P_even(x) and P_odd(x), where P' is the FRI reduced polynomial,
|
||||||
@ -167,6 +204,15 @@ fn verify_fri_proof<F: Field>(
|
|||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
challenger.observe_hash(proof.commit_phase_merkle_roots.last().unwrap());
|
challenger.observe_hash(proof.commit_phase_merkle_roots.last().unwrap());
|
||||||
|
|
||||||
|
// Check PoW.
|
||||||
|
ensure!(
|
||||||
|
hash_n_to_1(vec![challenger.get_challenge(), proof.pow_witness], false)
|
||||||
|
.to_canonical_u64()
|
||||||
|
.leading_zeros()
|
||||||
|
>= config.proof_of_work_bits,
|
||||||
|
"Invalid proof of work witness."
|
||||||
|
);
|
||||||
|
|
||||||
// Check that parameters are coherent.
|
// Check that parameters are coherent.
|
||||||
ensure!(
|
ensure!(
|
||||||
config.num_query_rounds == proof.query_round_proofs.len(),
|
config.num_query_rounds == proof.query_round_proofs.len(),
|
||||||
@ -228,7 +274,7 @@ fn verify_fri_proof<F: Field>(
|
|||||||
last_e_x_minus,
|
last_e_x_minus,
|
||||||
betas[config.reduction_count - 1],
|
betas[config.reduction_count - 1],
|
||||||
);
|
);
|
||||||
// Final check of FRI. After all the reduction, we check that the final polynomial is equal
|
// Final check of FRI. After all the reductions, we check that the final polynomial is equal
|
||||||
// to the one sent by the prover.
|
// to the one sent by the prover.
|
||||||
ensure!(
|
ensure!(
|
||||||
proof.final_poly.eval(subgroup_x.square()) == purported_eval,
|
proof.final_poly.eval(subgroup_x.square()) == purported_eval,
|
||||||
@ -260,7 +306,7 @@ mod tests {
|
|||||||
let config = FriConfig {
|
let config = FriConfig {
|
||||||
reduction_count,
|
reduction_count,
|
||||||
num_query_rounds,
|
num_query_rounds,
|
||||||
proof_of_work_bits: 0,
|
proof_of_work_bits: 2,
|
||||||
reduction_arity_bits: Vec::new(),
|
reduction_arity_bits: Vec::new(),
|
||||||
};
|
};
|
||||||
let mut challenger = Challenger::new();
|
let mut challenger = Challenger::new();
|
||||||
|
|||||||
@ -5,7 +5,6 @@ use crate::hash::GMIMC_ROUNDS;
|
|||||||
use crate::hash::{compress, hash_or_noop};
|
use crate::hash::{compress, hash_or_noop};
|
||||||
use crate::proof::{Hash, HashTarget};
|
use crate::proof::{Hash, HashTarget};
|
||||||
use crate::target::Target;
|
use crate::target::Target;
|
||||||
use crate::util::reverse_index_bits;
|
|
||||||
use crate::wire::Wire;
|
use crate::wire::Wire;
|
||||||
use anyhow::{ensure, Result};
|
use anyhow::{ensure, Result};
|
||||||
|
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
use crate::field::field::Field;
|
use crate::field::field::Field;
|
||||||
use crate::hash::{compress, hash_n_to_hash, hash_or_noop};
|
use crate::hash::{compress, hash_or_noop};
|
||||||
use crate::merkle_proofs::MerkleProof;
|
use crate::merkle_proofs::MerkleProof;
|
||||||
use crate::proof::Hash;
|
use crate::proof::Hash;
|
||||||
use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place};
|
use crate::util::{log2_strict, reverse_bits, reverse_index_bits_in_place};
|
||||||
@ -33,11 +33,11 @@ impl<F: Field> MerkleTree<F> {
|
|||||||
if l.len() == 1 {
|
if l.len() == 1 {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
layers.push(
|
let next_layer = l
|
||||||
l.chunks(2)
|
.chunks(2)
|
||||||
.map(|chunk| compress(chunk[0], chunk[1]))
|
.map(|chunk| compress(chunk[0], chunk[1]))
|
||||||
.collect::<Vec<_>>(),
|
.collect::<Vec<_>>();
|
||||||
);
|
layers.push(next_layer);
|
||||||
}
|
}
|
||||||
let root = layers.pop().unwrap()[0];
|
let root = layers.pop().unwrap()[0];
|
||||||
Self {
|
Self {
|
||||||
|
|||||||
@ -110,6 +110,8 @@ pub struct FriProof<F: Field> {
|
|||||||
pub query_round_proofs: Vec<FriQueryRound<F>>,
|
pub query_round_proofs: Vec<FriQueryRound<F>>,
|
||||||
/// The final polynomial in coefficient form.
|
/// The final polynomial in coefficient form.
|
||||||
pub final_poly: PolynomialCoeffs<F>,
|
pub final_poly: PolynomialCoeffs<F>,
|
||||||
|
/// Witness showing that the prover did PoW.
|
||||||
|
pub pow_witness: F,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Represents a single FRI query, i.e. a path through the reduction tree.
|
/// Represents a single FRI query, i.e. a path through the reduction tree.
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user