|
@ -20,7 +20,7 @@ use folding_schemes::{ |
|
|
use folding_schemes::{folding::nova::decider_eth_circuit::DeciderEthCircuit, FoldingScheme};
|
|
|
use folding_schemes::{folding::nova::decider_eth_circuit::DeciderEthCircuit, FoldingScheme};
|
|
|
use num_bigint::BigUint;
|
|
|
use num_bigint::BigUint;
|
|
|
use num_traits::Num;
|
|
|
use num_traits::Num;
|
|
|
use std::marker::PhantomData;
|
|
|
|
|
|
|
|
|
use std::{marker::PhantomData, time::Instant};
|
|
|
use utils::setup;
|
|
|
use utils::setup;
|
|
|
mod utils;
|
|
|
mod utils;
|
|
|
|
|
|
|
|
@ -78,99 +78,105 @@ impl FCircuit for BTCBlockCheckerFCircuit { |
|
|
}
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
fn main() {}
|
|
|
|
|
|
|
|
|
|
|
|
#[cfg(test)]
|
|
|
|
|
|
mod tests {
|
|
|
|
|
|
use super::*;
|
|
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
|
fn run_main() {
|
|
|
|
|
|
// this is done to avoid computing large circuits
|
|
|
|
|
|
let file = include_str!("./data/btc-blocks.json");
|
|
|
|
|
|
let (mut prev_block_hash, blocks) = read_blocks(20, 1, file);
|
|
|
|
|
|
|
|
|
|
|
|
let mut blocks_prepared = vec![];
|
|
|
|
|
|
for batch in blocks.iter() {
|
|
|
|
|
|
let block_hashes =
|
|
|
|
|
|
serde_json::from_value::<Vec<String>>(batch.get("blockHashes").unwrap().clone())
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
let block_headers =
|
|
|
|
|
|
serde_json::from_value::<Vec<Vec<u8>>>(batch.get("blockHeaders").unwrap().clone())
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
for (i, (block_hash, block_header)) in
|
|
|
|
|
|
block_hashes.iter().zip(block_headers).enumerate()
|
|
|
|
|
|
{
|
|
|
|
|
|
let block = Block {
|
|
|
|
|
|
block_header,
|
|
|
|
|
|
block_hash: block_hash.to_string(),
|
|
|
|
|
|
prev_block_hash,
|
|
|
|
|
|
};
|
|
|
|
|
|
blocks_prepared.push(block.clone());
|
|
|
|
|
|
prev_block_hash = block_hash.to_string();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
fn main() {
|
|
|
|
|
|
let file = include_str!("./data/btc-blocks.json");
|
|
|
|
|
|
let (mut prev_block_hash, blocks) = read_blocks(100, 1, file);
|
|
|
|
|
|
|
|
|
|
|
|
let mut blocks_prepared = vec![];
|
|
|
|
|
|
for batch in blocks.iter() {
|
|
|
|
|
|
let block_hashes =
|
|
|
|
|
|
serde_json::from_value::<Vec<String>>(batch.get("blockHashes").unwrap().clone())
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
let block_headers =
|
|
|
|
|
|
serde_json::from_value::<Vec<Vec<u8>>>(batch.get("blockHeaders").unwrap().clone())
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
for (block_hash, block_header) in block_hashes.iter().zip(block_headers) {
|
|
|
|
|
|
let block = Block {
|
|
|
|
|
|
block_header,
|
|
|
|
|
|
block_hash: block_hash.to_string(),
|
|
|
|
|
|
prev_block_hash,
|
|
|
|
|
|
};
|
|
|
|
|
|
blocks_prepared.push(block.clone());
|
|
|
|
|
|
prev_block_hash = block_hash.to_string();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
type NOVA = Nova<
|
|
|
|
|
|
Projective,
|
|
|
|
|
|
GVar,
|
|
|
|
|
|
Projective2,
|
|
|
|
|
|
GVar2,
|
|
|
|
|
|
BTCBlockCheckerFCircuit<Fr>,
|
|
|
|
|
|
KZG<'static, Bn254>,
|
|
|
|
|
|
Pedersen<Projective2>,
|
|
|
|
|
|
>;
|
|
|
|
|
|
type DECIDER = Decider<
|
|
|
|
|
|
Projective,
|
|
|
|
|
|
GVar,
|
|
|
|
|
|
Projective2,
|
|
|
|
|
|
GVar2,
|
|
|
|
|
|
BTCBlockCheckerFCircuit<Fr>,
|
|
|
|
|
|
KZG<'static, Bn254>,
|
|
|
|
|
|
Pedersen<Projective2>,
|
|
|
|
|
|
Groth16<Bn254>, // here we define the Snark to use in the decider
|
|
|
|
|
|
NOVA, // here we define the FoldingScheme to use
|
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
|
|
let n_blocks_checked = blocks_prepared.len();
|
|
|
|
|
|
let circuit = BTCBlockCheckerFCircuit::<Fr>::new(blocks_prepared.clone());
|
|
|
|
|
|
let (prover_params, poseidon_config, kzg_vk) = setup(circuit.clone());
|
|
|
|
|
|
let z_0 = vec![Fr::from(0)];
|
|
|
|
|
|
let mut nova = NOVA::init(&prover_params, circuit, z_0.clone()).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
for _ in 0..n_blocks_checked {
|
|
|
|
|
|
nova.prove_step().unwrap();
|
|
|
|
|
|
let current_state = nova.z_i[0].into_bigint();
|
|
|
|
|
|
println!("Checked block: {}", current_state);
|
|
|
|
|
|
|
|
|
type NOVA = Nova<
|
|
|
|
|
|
Projective,
|
|
|
|
|
|
GVar,
|
|
|
|
|
|
Projective2,
|
|
|
|
|
|
GVar2,
|
|
|
|
|
|
BTCBlockCheckerFCircuit<Fr>,
|
|
|
|
|
|
KZG<'static, Bn254>,
|
|
|
|
|
|
Pedersen<Projective2>,
|
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
|
|
type DECIDER = Decider<
|
|
|
|
|
|
Projective,
|
|
|
|
|
|
GVar,
|
|
|
|
|
|
Projective2,
|
|
|
|
|
|
GVar2,
|
|
|
|
|
|
BTCBlockCheckerFCircuit<Fr>,
|
|
|
|
|
|
KZG<'static, Bn254>,
|
|
|
|
|
|
Pedersen<Projective2>,
|
|
|
|
|
|
Groth16<Bn254>,
|
|
|
|
|
|
NOVA,
|
|
|
|
|
|
>;
|
|
|
|
|
|
|
|
|
|
|
|
let n_blocks_checked = blocks_prepared.len();
|
|
|
|
|
|
let circuit = BTCBlockCheckerFCircuit::<Fr>::new(blocks_prepared.clone());
|
|
|
|
|
|
let (prover_params, poseidon_config, kzg_vk) = setup(circuit.clone());
|
|
|
|
|
|
let z_0 = vec![Fr::from(0)];
|
|
|
|
|
|
let mut nova = NOVA::init(&prover_params, circuit, z_0.clone()).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
println!("Computing folds...");
|
|
|
|
|
|
let now = Instant::now();
|
|
|
|
|
|
for i in 0..n_blocks_checked {
|
|
|
|
|
|
let current_state = nova.z_i[0].into_bigint();
|
|
|
|
|
|
if i % 10 == 0 {
|
|
|
|
|
|
println!("--- At block: {}/{} ---", current_state, n_blocks_checked);
|
|
|
}
|
|
|
}
|
|
|
|
|
|
|
|
|
let circuit = DeciderEthCircuit::<
|
|
|
|
|
|
Projective,
|
|
|
|
|
|
GVar,
|
|
|
|
|
|
Projective2,
|
|
|
|
|
|
GVar2,
|
|
|
|
|
|
KZG<Bn254>,
|
|
|
|
|
|
Pedersen<Projective2>,
|
|
|
|
|
|
>::from_nova::<BTCBlockCheckerFCircuit<Fr>>(nova.clone())
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
let mut rng = rand::rngs::OsRng;
|
|
|
|
|
|
|
|
|
|
|
|
println!("Starting setup...");
|
|
|
|
|
|
let (g16_pk, g16_vk) =
|
|
|
|
|
|
Groth16::<Bn254>::circuit_specific_setup(circuit.clone(), &mut rng).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
// decider proof generation
|
|
|
|
|
|
println!("Generating proof...");
|
|
|
|
|
|
let decider_pp = (poseidon_config.clone(), g16_pk, prover_params.cs_params);
|
|
|
|
|
|
let proof = DECIDER::prove(decider_pp, rng, nova.clone()).unwrap();
|
|
|
|
|
|
|
|
|
|
|
|
// decider proof verification
|
|
|
|
|
|
println!("Verifying proof...");
|
|
|
|
|
|
let decider_vp = (poseidon_config, g16_vk, kzg_vk);
|
|
|
|
|
|
let verified = DECIDER::verify(
|
|
|
|
|
|
decider_vp, nova.i, nova.z_0, nova.z_i, &nova.U_i, &nova.u_i, proof,
|
|
|
|
|
|
)
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
assert!(verified);
|
|
|
|
|
|
|
|
|
nova.prove_step().unwrap();
|
|
|
}
|
|
|
}
|
|
|
|
|
|
let elapsed = now.elapsed();
|
|
|
|
|
|
println!(
|
|
|
|
|
|
"Done folding. Checked {} blocks in: {:.2?}",
|
|
|
|
|
|
n_blocks_checked, elapsed
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
let circuit = DeciderEthCircuit::<
|
|
|
|
|
|
Projective,
|
|
|
|
|
|
GVar,
|
|
|
|
|
|
Projective2,
|
|
|
|
|
|
GVar2,
|
|
|
|
|
|
KZG<Bn254>,
|
|
|
|
|
|
Pedersen<Projective2>,
|
|
|
|
|
|
>::from_nova::<BTCBlockCheckerFCircuit<Fr>>(nova.clone())
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
let mut rng = rand::rngs::OsRng;
|
|
|
|
|
|
|
|
|
|
|
|
// decider setup
|
|
|
|
|
|
println!("Starting setup...");
|
|
|
|
|
|
let now = Instant::now();
|
|
|
|
|
|
let (g16_pk, g16_vk) =
|
|
|
|
|
|
Groth16::<Bn254>::circuit_specific_setup(circuit.clone(), &mut rng).unwrap();
|
|
|
|
|
|
let elapsed = now.elapsed();
|
|
|
|
|
|
println!("Setup done in: {:.2?}", elapsed);
|
|
|
|
|
|
|
|
|
|
|
|
// decider proof generation
|
|
|
|
|
|
println!("Generating proof...");
|
|
|
|
|
|
let now = Instant::now();
|
|
|
|
|
|
let decider_pp = (poseidon_config.clone(), g16_pk, prover_params.cs_params);
|
|
|
|
|
|
let proof = DECIDER::prove(decider_pp, rng, nova.clone()).unwrap();
|
|
|
|
|
|
let elapsed = now.elapsed();
|
|
|
|
|
|
println!("Proof generated in: {:.2?}", elapsed);
|
|
|
|
|
|
|
|
|
|
|
|
// decider proof verification
|
|
|
|
|
|
println!("Verifying proof...");
|
|
|
|
|
|
let decider_vp = (poseidon_config, g16_vk, kzg_vk);
|
|
|
|
|
|
let verified = DECIDER::verify(
|
|
|
|
|
|
decider_vp, nova.i, nova.z_0, nova.z_i, &nova.U_i, &nova.u_i, proof,
|
|
|
|
|
|
)
|
|
|
|
|
|
.unwrap();
|
|
|
|
|
|
assert!(verified);
|
|
|
}
|
|
|
}
|