2019-06-22 23:24:01 +03:00
|
|
|
use crate::error_type::AppResult;
|
|
|
|
use crate::request_response::Response;
|
|
|
|
|
|
|
|
use linked_hash_map::LinkedHashMap;
|
|
|
|
use serde_json::Value;
|
|
|
|
|
|
|
|
pub struct ProofManager {
|
|
|
|
// map from job id to verify status
|
|
|
|
proofs: LinkedHashMap<u64, u8>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl ProofManager {
|
|
|
|
|
|
|
|
pub fn new() -> Self {
|
|
|
|
ProofManager {
|
|
|
|
proofs: LinkedHashMap::new(),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-06-23 12:20:20 +03:00
|
|
|
pub fn verify(&mut self, proof_id: u64, public_par: [f64; 5], proof: [f64; 8]) -> AppResult<Value> {
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
use bellman::pairing::bn256::*;
|
|
|
|
use bellman::groth16::{
|
|
|
|
Proof,
|
|
|
|
VerifyingKey,
|
|
|
|
verify_proof,
|
|
|
|
prepare_verifying_key
|
|
|
|
};
|
|
|
|
|
|
|
|
use bellman::pairing::ff::{
|
|
|
|
PrimeField,
|
|
|
|
PrimeFieldRepr,
|
|
|
|
Field
|
|
|
|
};
|
|
|
|
|
|
|
|
use bellman::pairing::{
|
|
|
|
CurveAffine,
|
|
|
|
EncodedPoint
|
|
|
|
};
|
|
|
|
|
|
|
|
use std::io::{self, Read, Cursor, Seek, SeekFrom, Write};
|
|
|
|
|
2019-06-22 23:24:01 +03:00
|
|
|
// verify mock
|
2019-06-23 12:20:20 +03:00
|
|
|
let mut result: u8 = 1;
|
|
|
|
if proof[0] != 8.51065254754666e75 {
|
|
|
|
result = 0
|
|
|
|
}
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
// verify proof -------------------------------------------------------------------------------------
|
|
|
|
|
|
|
|
// import verification key --------------------------------------------
|
|
|
|
|
|
|
|
//vk.alpha_g1
|
|
|
|
let mut hex_string = hex::decode("2c2cb1812fb05d4f31791c66ff995d756b73162f3bb016a5c114befe5cd7903e").unwrap();
|
|
|
|
hex_string.append(hex::decode("0abc1f8a5d49cb2dbda15b5a8b7cd81bec0a581e7c2e16f79446af2d2f5340c0").unwrap().as_mut());
|
|
|
|
//vk.beta_g1 = vk.alpha_g1 - ZoKrates does not return that and it is not neaded for verification
|
|
|
|
hex_string.append(hex::decode("1fea09defec64586a976a33dbfb70961fc7e03fb6f4d5a1e074f97312ce789cd").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("006653d8d2e65ab55fa795c44971eabcc6dbb1dd383c7a8a20de68486eb28154").unwrap().as_mut());
|
|
|
|
//vk.beta_g2
|
|
|
|
hex_string.append(hex::decode("071644533641f7e3acb8606328c591853b2bc27253f29bc11d008a67996fc07f").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("26ca2720c073a085d8452aef541aac280879971c09b199a6e0f21bf36745e1d8").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0b17104896ed701b6d52279992c1f20d558bc0de8284087645633bf3ca1a0c98").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("2c10eb5b6c0ca42ede8cdcf60642c6dca040abe9abb8294948f4aa0be59a0d42").unwrap().as_mut());
|
|
|
|
//vk.gamma_g2
|
|
|
|
hex_string.append(hex::decode("0afbadec2ecafdd62278c7021095660f5786f445c040e628e4ed1a410454b582").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("038aa6f04ee254a97e2b75ea1f30e36785b6cde4dfd3a2371e058ce089b9ad51").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("077720bb216fb0051c5e153c1bd9aa36a678173b9c13e8d3a83cb5a75ca36948").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("1f9b58e9abde296abc3c3bab8fb0be2a4f497d8e5d9d463997d316e9cc558a7d").unwrap().as_mut());
|
|
|
|
//vk.delta_g1 = vk.alpha_g1 - ZoKrates does not return that and it is not neaded for verification
|
|
|
|
hex_string.append(hex::decode("1fea09defec64586a976a33dbfb70961fc7e03fb6f4d5a1e074f97312ce789cd").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("006653d8d2e65ab55fa795c44971eabcc6dbb1dd383c7a8a20de68486eb28154").unwrap().as_mut());
|
|
|
|
//vk.delta_g2
|
|
|
|
hex_string.append(hex::decode("16526b9b519fa544d3f9ce35a5f4afa7aac0aa4dd54421c4864b3fe8d2415f41").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("24e24f35699cca59416a7f43c0e93e148b2353440978994df8f81603a46f8839").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("299f9f09280310aedf63055c5ce76feb16557ed7ff11ba35adad718102b5651a").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0c4a2fc4db77ef6c19511b2ffb369981cebbffcb5337a671e1ad678b460ac5e9").unwrap().as_mut());
|
|
|
|
//vk.ic len
|
|
|
|
hex_string.append(6u32.to_be_bytes().to_vec().as_mut());
|
|
|
|
//vk.ic
|
|
|
|
hex_string.append(hex::decode("2f910078bf5092a7ea9d3ce750b7b5399b101509adb8017a6e12fa1a4c638d5b").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0b76454d4300571c8d86714b4e5ef095688b51080e674425e8e5edb201f64128").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("2922a307d415f70c8df6f14b664c46df12a89cd3a89cf7960663907bf9483b68").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("1bc30a719ddc0099f557cca61a0687766e6275fc98b185baa77735b93bf2a0ef").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0201dc8c8faa3dc5b8eec85f029d2482bf11a6b46d5f8e4d9f17d41ac3e4c9c1").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0a1d62c1142c92dff75b53d5a572fd7a013708118acf10f718c61fb6226160f5").unwrap().as_mut());
|
|
|
|
|
|
|
|
hex_string.append(hex::decode("02276f5896610ec573cd6cdc6e47c69e756362d2b1b1c51c5ab90ac838d1a898").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("13fa6cc7987f4f3118f6ee3ab85dcd708df17050636d487914077348e0af05b1").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0778ae3718fd7f48564bc33b60ec4f39a238e97cb4cc0bbd4ff37119942ff7d4").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0282e96481744ee21524d802b3e524bf0596bb37bb63e5ed37c77fc1a5c8e89d").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("1ce40e230695bdab7d2ff7ebcf6e6fedb68d1a320238fc98845b151ae4ee3b54").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("0feac76664d37b57a4ea5a774252bb82355294e55635a8aeb7a1327405d27128").unwrap().as_mut());
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-06-23 12:20:20 +03:00
|
|
|
let mut c = Cursor::new(Vec::new());
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
c.write_all(hex_string.as_slice()).unwrap();
|
2019-06-23 12:20:20 +03:00
|
|
|
c.seek(SeekFrom::Start(0)).unwrap();
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
let vk : VerifyingKey<Bn256> = VerifyingKey::read(c).unwrap();
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
let prepared_vk = prepare_verifying_key(&vk);
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
// import proof -------------------------------------------------------
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
// a
|
|
|
|
let mut hex_string = hex::decode("12d0dbcfc1da3ea29bc017288fceea3929401f4f12dbd0bba73781420d31aa2d").unwrap();
|
|
|
|
hex_string.append(hex::decode("2811c1eaa63f4a804951bd7f994cbb6bea9df64591793b8392400e8756d1bca7").unwrap().as_mut());
|
|
|
|
// b
|
|
|
|
hex_string.append(hex::decode("04c33f68e1bd55be0928b086c647debcdf7aa0e3c3efc6a8efbc2596a77a0e67").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("17e7392e0e3ec2b5701e675e6e0569330d03ffffe476fc8d63cfeaa0ba1c8a97").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("2fc402693a54cd1b176abeed209674f2f12ced1496c6ce27ba8cf16903daa4cc").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("2c47efba3f4f260da643bb6427d08b551bb3446537d6ac4857d611be2355a446").unwrap().as_mut());
|
|
|
|
|
|
|
|
// c
|
|
|
|
hex_string.append(hex::decode("04d40f14694092d0f70890a20492b2b68e7eaabdcee744e519678d687c9c3ed0").unwrap().as_mut());
|
|
|
|
hex_string.append(hex::decode("28de140e393154b0e70b3ef12806af963a4a33b45c24e7864391093b6028fa2b").unwrap().as_mut());
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
let mut c = Cursor::new(Vec::new());
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
c.write_all(hex_string.as_slice()).unwrap();
|
|
|
|
c.seek(SeekFrom::Start(0)).unwrap();
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-07-04 17:34:34 +03:00
|
|
|
let mut g1_repr = <bellman::pairing::bn256::G1Affine as CurveAffine>::Uncompressed::empty();
|
|
|
|
let mut g2_repr = <bellman::pairing::bn256::G2Affine as CurveAffine>::Uncompressed::empty();
|
|
|
|
|
|
|
|
c.read_exact(g1_repr.as_mut()).unwrap();
|
|
|
|
let a = g1_repr
|
|
|
|
.into_affine()
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
|
|
|
.and_then(|e| if e.is_zero() {
|
|
|
|
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
|
|
|
} else {
|
|
|
|
Ok(e)
|
|
|
|
}).unwrap();
|
|
|
|
|
|
|
|
c.read_exact(g2_repr.as_mut()).unwrap();
|
|
|
|
let b = g2_repr
|
|
|
|
.into_affine()
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
|
|
|
.and_then(|e| if e.is_zero() {
|
|
|
|
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
|
|
|
} else {
|
|
|
|
Ok(e)
|
|
|
|
}).unwrap();
|
|
|
|
|
|
|
|
c.read_exact(g1_repr.as_mut()).unwrap();
|
|
|
|
let c = g1_repr
|
|
|
|
.into_affine()
|
|
|
|
.map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))
|
|
|
|
.and_then(|e| if e.is_zero() {
|
|
|
|
Err(io::Error::new(io::ErrorKind::InvalidData, "point at infinity"))
|
|
|
|
} else {
|
|
|
|
Ok(e)
|
|
|
|
}).unwrap();
|
|
|
|
|
|
|
|
let proof : Proof<Bn256> = Proof {a: a, b: b, c: c};
|
|
|
|
|
|
|
|
// import public inputs -----------------------------------------------
|
|
|
|
|
|
|
|
let in_1 = hex::decode("00000000000000000000000000000000c6481e22c5ff4164af680b8cfaa5e8ed").unwrap();
|
|
|
|
let in_2 = hex::decode("000000000000000000000000000000003120eeff89c4f307c4a6faaae059ce10").unwrap();
|
|
|
|
let in_3 = hex::decode("000000000000000000000000000000005b6d7d198c48c17c9540d29275a04662").unwrap();
|
|
|
|
let in_4 = hex::decode("00000000000000000000000000000000f7a9aa434629a33c84eec3e16e196f27").unwrap();
|
|
|
|
let in_5 = hex::decode("0000000000000000000000000000000000000000000000000000000000000001").unwrap();
|
|
|
|
|
|
|
|
let mut repr_in_1 = Fr::zero().into_repr();
|
|
|
|
repr_in_1.read_be(&in_1[..]).expect("pack new hash as field element");
|
|
|
|
let in_1_fr = Fr::from_repr(repr_in_1).expect("must be a valud new representation");
|
|
|
|
|
|
|
|
let mut repr_in_2 = Fr::zero().into_repr();
|
|
|
|
repr_in_2.read_be(&in_2[..]).expect("pack new hash as field element");
|
|
|
|
let in_2_fr = Fr::from_repr(repr_in_2).expect("must be a valud new representation");
|
|
|
|
|
|
|
|
let mut repr_in_3 = Fr::zero().into_repr();
|
|
|
|
repr_in_3.read_be(&in_3[..]).expect("pack new hash as field element");
|
|
|
|
let in_3_fr = Fr::from_repr(repr_in_3).expect("must be a valud new representation");
|
|
|
|
|
|
|
|
let mut repr_in_4 = Fr::zero().into_repr();
|
|
|
|
repr_in_4.read_be(&in_4[..]).expect("pack new hash as field element");
|
|
|
|
let in_4_fr = Fr::from_repr(repr_in_4).expect("must be a valud new representation");
|
|
|
|
|
|
|
|
let mut repr_in_5 = Fr::zero().into_repr();
|
|
|
|
repr_in_5.read_be(&in_5[..]).expect("pack new hash as field element");
|
|
|
|
let in_5_fr = Fr::from_repr(repr_in_5).expect("must be a valud new representation");
|
|
|
|
|
|
|
|
let public_inputs = vec![in_1_fr, in_2_fr, in_3_fr, in_4_fr, in_5_fr];
|
|
|
|
|
|
|
|
let is_valid = verify_proof(&prepared_vk, &proof, &public_inputs).expect("must verify a proof");
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-06-23 12:20:20 +03:00
|
|
|
// update proof status
|
|
|
|
self.proofs.insert(proof_id, result);
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-06-23 12:20:20 +03:00
|
|
|
let response = Response::Verify {
|
|
|
|
result : result,
|
|
|
|
};
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-06-23 12:20:20 +03:00
|
|
|
serde_json::to_value(response).map_err(Into::into)
|
|
|
|
}
|
2019-06-22 23:24:01 +03:00
|
|
|
|
2019-06-23 12:20:20 +03:00
|
|
|
pub fn check(&self, proof_id: u64) -> AppResult<Value> {
|
|
|
|
let status = self.proof_status(proof_id)?;
|
|
|
|
let response = Response::Check { verified: status };
|
|
|
|
|
|
|
|
serde_json::to_value(response).map_err(Into::into)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn proof_status(&self, proof_id: u64) -> AppResult<u8> {
|
|
|
|
let status = self
|
|
|
|
.proofs
|
|
|
|
.get(&proof_id)
|
|
|
|
.ok_or_else(|| format!("Proof with id {} wasn't found", proof_id))?;
|
|
|
|
|
|
|
|
Ok(*status)
|
|
|
|
}
|
2019-06-22 23:24:01 +03:00
|
|
|
}
|