From 9c14bbf8da57036fc7f9c5c950516743b5ab0153 Mon Sep 17 00:00:00 2001 From: afkbyte Date: Mon, 27 May 2024 11:09:31 -0400 Subject: [PATCH] the sanity checks work now holy shit --- arbitrator/Cargo.lock | 1 + arbitrator/prover/Cargo.toml | 1 + arbitrator/prover/src/kzgbn254.rs | 127 ++++++++++++++++++++++++------ 3 files changed, 103 insertions(+), 26 deletions(-) diff --git a/arbitrator/Cargo.lock b/arbitrator/Cargo.lock index 4abaf0605..5973ff429 100644 --- a/arbitrator/Cargo.lock +++ b/arbitrator/Cargo.lock @@ -1468,6 +1468,7 @@ dependencies = [ "nom", "nom-leb128", "num", + "num-bigint", "rayon", "rust-kzg-bn254", "rustc-demangle", diff --git a/arbitrator/prover/Cargo.toml b/arbitrator/prover/Cargo.toml index 06e10c83f..555cd63cf 100644 --- a/arbitrator/prover/Cargo.toml +++ b/arbitrator/prover/Cargo.toml @@ -35,6 +35,7 @@ ark-std = "0.4.0" ark-ff = "0.4.0" ark-ec = "0.4.0" ark-serialize = "0.4.0" +num-bigint = "0.4" kzgbn254 = { git = "https://github.com/afkbyte/rust-kzg-bn254.git", branch = "master", package = "rust-kzg-bn254" } diff --git a/arbitrator/prover/src/kzgbn254.rs b/arbitrator/prover/src/kzgbn254.rs index 5e133d0fc..41794be8b 100644 --- a/arbitrator/prover/src/kzgbn254.rs +++ b/arbitrator/prover/src/kzgbn254.rs @@ -1,22 +1,23 @@ use crate::utils::Bytes32; -use ark_ec::AffineRepr; +use ark_ec::{AffineRepr, CurveGroup, pairing::Pairing}; use kzgbn254::{ kzg::Kzg, blob::Blob, - helpers::{remove_empty_byte_from_padded_bytes, set_bytes_canonical_manual} + helpers::{remove_empty_byte_from_padded_bytes, to_fr_array} }; use eyre::{ensure, Result, WrapErr}; -use ark_bn254::{Fr, G1Affine, G1Projective, G2Affine}; +use ark_bn254::{Bn254, Fr, G1Affine, G1Projective, G2Affine, G2Projective, Fq, g2, g1}; use num::BigUint; use serde::{de::Error as _, Deserialize}; use sha2::{Digest, Sha256}; use std::{convert::TryFrom, io::Write}; -use hex::decode; +use hex::{encode, decode}; use ark_std::{ops::Mul, ops::Add}; use ark_serialize::CanonicalSerialize; -use ark_ff::{PrimeField, Field}; +use ark_ff::{PrimeField, Field, Fp}; use ark_ff::BigInteger256; +use num::Zero; struct HexBytesParser; @@ -92,8 +93,8 @@ pub fn prove_kzg_preimage_bn254( let unpadded_preimage_vec = remove_empty_byte_from_padded_bytes(preimage); let unpadded_preimage = unpadded_preimage_vec.as_slice(); - println!("UNPADDED PREIMAGE: {:?}", unpadded_preimage); - println!("PREIMAGE: {:?}", preimage); + println!("unpadded_preimage {:?}", unpadded_preimage); + println!("padded_preimage {:?}", preimage); // repad it here, TODO: need to ask to change the interface for this let blob = kzgbn254::blob::Blob::from_bytes_and_pad(unpadded_preimage); @@ -106,8 +107,6 @@ pub fn prove_kzg_preimage_bn254( let mut expected_hash: Bytes32 = Sha256::digest(&*commitment_bytes).into(); expected_hash[0] = 1; - println!("Expected hash: {:?}", expected_hash); - println!("Hash: {:?}", hash); ensure!( hash == expected_hash, "Trying to prove versioned hash {} preimage but recomputed hash {}", @@ -124,9 +123,6 @@ pub fn prove_kzg_preimage_bn254( //let offset_usize = usize::try_from(offset)?; let proving_offset = offset; - // log proving offset - println!("Proving offset: {}", proving_offset); - // address proving past end edge case later // let proving_past_end = offset_usize >= preimage.len(); // if proving_past_end { @@ -144,47 +140,118 @@ pub fn prove_kzg_preimage_bn254( let offset_usize = offset as usize; // Convert offset to usize proven_y = proven_y[offset_usize..(offset_usize + 32)].to_vec(); + // convert proven_y into fr + let proven_y_fr = to_fr_array(&proven_y); + + + println!("proven_y_bigint {:?}", num_bigint::BigUint::from(proven_y_fr[0])); + + // values from golang + let nums = [ + 10452980113691647213u64, + 8307771156814818368u64, + 403489732867499594u64, + 241724799641539493u64, + ]; + + // Convert the list of integers into a BigUint + let mut big_int = BigUint::zero(); + for &num in nums.iter().rev() { + big_int = big_int << 64; // Shift left by 64 bits (the size of each u64) + big_int += num; + } + + // Convert the BigUint to an Fr element + let fr_element = Fr::from(big_int); + println!("fr_element {:?}", fr_element); + + let polynomial = blob.to_polynomial().unwrap(); let length: usize = blob.len(); - let proven_y_fr = set_bytes_canonical_manual(&proven_y.as_slice()); + let proven_y_bigint: num_bigint::BigUint = proven_y_fr[0].into(); // are there cases where the g2 generator won't be the first element? - let g2_generator = kzg.get_g2_points().get(0).unwrap().clone(); - let z_g2= g2_generator * proven_y_fr; - let g2_tau = g2_generator.mul_bigint(BigInteger256::from(2u64)); - let g2_tau_minus_g2_z = g2_tau - z_g2; + let g2_generator = g2::G2Affine::generator(); + + let z_g2= g2_generator.mul_bigint(&proven_y_bigint.to_u64_digits() ); + + let g2_tau: g2::G2Affine = kzg.get_g2_points().get(1).unwrap().clone(); + + let g2tau_x1: num_bigint::BigUint = g2_tau.x.c0.into(); + println!("x_c0 G2TAU as BigInteger: {}", g2tau_x1); + + let g2_tau_minus_g2_z = g2_tau; - z_g2; let mut g2_tau_minus_g2_z_uncompressed_bytes = Vec::new(); g2_tau_minus_g2_z.serialize_uncompressed(&mut g2_tau_minus_g2_z_uncompressed_bytes).unwrap(); // required roots of unity are the first polynomial length roots in the expanded set let roots_of_unity = kzg.get_expanded_roots_of_unity(); - let required_roots_of_unity = &roots_of_unity[..polynomial.len()]; + let required_roots_of_unity = &roots_of_unity[1..polynomial.len()+1]; // TODO: ask for interface alignment later let kzg_proof = match kzg.compute_kzg_proof(&blob_polynomial, offset as u64, &required_roots_of_unity.to_vec()) { Ok(proof) => proof, Err(err) => return Err(err.into()), }; + // print required roots of unity + println!("required_roots_of_unity {:?}", required_roots_of_unity); + let mut kzg_proof_uncompressed_bytes = Vec::new(); kzg_proof.serialize_uncompressed(&mut kzg_proof_uncompressed_bytes).unwrap(); - //print the length of each byte array written - println!("hash length: {}", hash.len()); - println!("padded_proving_offset_bytes length: {}", padded_proving_offset_bytes.len()); - println!("proven_y length: {}", proven_y.len()); - println!("g2_tau_minus_g2_z_uncompressed_bytes length: {}", g2_tau_minus_g2_z_uncompressed_bytes.len()); - println!("commitment_bytes length: {}", commitment_bytes.len()); - println!("kzg_proof_uncompressed_bytes length: {}", kzg_proof_uncompressed_bytes.len()); + let g2gen_x1: num_bigint::BigUint = g2_generator.x.c0.into(); + + println!("x_c0 as BigInteger: {}", g2gen_x1); + + // sanity check + let verified = kzg.verify_kzg_proof(blob_commitment, kzg_proof, proven_y_fr[0], Fr::from(0u64)); + println!("verified: {}", verified); + + // sanity check 2 + //BN254.G1Point memory commitmentMinusValue = BN254.plus(_commitment, BN254.negate(valueG1)); + // return BN254.pairing( + // commitmentMinusValue, + // BN254.generatorG2(), + // BN254.negate(_proof), + // _g2TauMinusZCommitG2 + // ); + + // Blob Commitment matches golang + // commit E([11751635630905918857119186162610564827152291944163949151543696319755436002382,8945166640620342368329477900333474847484176204111470609556695574973521462136]) + + let value_g1 = (G1Affine::generator() * proven_y_fr[0]).into_affine(); + let commit_minus_value = (blob_commitment - value_g1).into_affine(); + + println!("commit_minus_value {:?}", commit_minus_value); + + assert_eq!(blob_commitment.x.to_string(), "11751635630905918857119186162610564827152291944163949151543696319755436002382".to_string(), "Commitment x-coordinate does not match golang."); + assert_eq!(blob_commitment.y.to_string(), "8945166640620342368329477900333474847484176204111470609556695574973521462136".to_string(), "Commitment y-coordinate does not match golang."); + + // proven_y matches golang + // valueFr 333272405995201600837266485607900126160378066268259446184604564808435560485 + assert_eq!(proven_y_bigint.to_string(), "333272405995201600837266485607900126160378066268259446184604564808435560485".to_string(), "fr_element does not match golang."); + println!("kzg_proof {:?}", kzg_proof); + + let verified_sanity_pariing = pairings_verify(commit_minus_value, g2_generator, kzg_proof, g2_tau_minus_g2_z); + println!("verified SANITY PAIRING: {}", verified_sanity_pariing); out.write_all(&*hash)?; // hash [:32] out.write_all(&padded_proving_offset_bytes)?; // evaluation point [32:64] out.write_all(&*proven_y)?; // expected output [64:96] + out.write_all(g2_tau_minus_g2_z_uncompressed_bytes.as_slice())?; // g2TauMinusG2z [96:224] out.write_all(&*commitment_bytes)?; // kzg commitment [224:288] out.write_all(kzg_proof_uncompressed_bytes.as_slice())?; // proof [288:352] - + + // print each element in hex + // println!("hash: {}", hex::encode(hash)); + // println!("padded_proving_offset_bytes: {}", hex::encode(padded_proving_offset_bytes)); + println!("proven_y: {}", hex::encode(proven_y)); + // println!("g2_tau_minus_g2_z_uncompressed_bytes: {}", hex::encode(g2_tau_minus_g2_z_uncompressed_bytes)); + // println!("commitment_bytes: {}", hex::encode(commitment_bytes)); + // println!("kzg_proof_uncompressed_bytes: {}", hex::encode(kzg_proof_uncompressed_bytes)); // // pre encoded proof data // let hex_str = "0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000100757220666174686572732062726f7567687420666f7274682c206f6e2074681db5eb0b7f38e2373003e7ab7b7a2509cc2759214dd255514a9c28bb46cd1201294217923e1ecdd86ec74266a1423cf152f2a54295ae39339673fcd59e1db7292099e357166e69509eea101212adfc3d2ea0254cd5526381756dcc5a942f43762f2b0c30d1fb8b1dc0d8177e44b687fc39d41a8c831665ae1af58b2bebf74b72068bf472ebc0e26c297f8a9257c3f42a38af1e4612b60f6ac64d57dc272d50b1005a4f9eb6b109d60804cbbfa4e54753b4d3b262ef7f8269fb3c2a9939741cbd06f15529acc9d00f89345e4126d6f8c2e03da0e71b718bd4a63d1fbd315cac5c04341e21e9c059641601112f3c97db852dca3a1efffe61c413af70108bc46561"; @@ -197,3 +264,11 @@ pub fn prove_kzg_preimage_bn254( Ok(()) } + +fn pairings_verify(a1: G1Affine, a2: G2Affine, b1: G1Affine, b2: G2Affine) -> bool { + let neg_b1 = -b1; + let p = [a1, neg_b1]; + let q = [a2, b2]; + let result = Bn254::multi_pairing(p, q); + result.is_zero() +}