diff --git a/Cargo.toml b/Cargo.toml index 940d1b4..4eaf11c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,6 @@ [workspace] members = [ "multiplier", - "poseidon-tornado", "semaphore", "rln", ] diff --git a/poseidon-tornado/Cargo.toml b/poseidon-tornado/Cargo.toml deleted file mode 100644 index 8e67b12..0000000 --- a/poseidon-tornado/Cargo.toml +++ /dev/null @@ -1,45 +0,0 @@ -[package] -name = "poseidon-tornado" -version = "0.1.0" -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] - -# WASM operations -# wasmer = { version = "2.0" } -# fnv = { version = "1.0.3", default-features = false } -# num = { version = "0.4.0" } -# num-traits = { version = "0.2.0", default-features = false } -num-bigint = { version = "0.4", default-features = false, features = ["rand"] } - -# ZKP Generation -ark-ec = { version = "0.3.0", default-features = false, features = ["parallel"] } -# ark-ff = { version = "0.3.0", default-features = false, features = ["parallel", "asm"] } -ark-std = { version = "0.3.0", default-features = false, features = ["parallel"] } -ark-bn254 = { version = "0.3.0" } -ark-groth16 = { git = "https://github.com/arkworks-rs/groth16", rev = "765817f", features = ["parallel"] } -# ark-poly = { version = "^0.3.0", default-features = false, features = ["parallel"] } -#ark-relations = { version = "0.3.0", default-features = false, path = "../../../arkworks-rs/snark/relations", features = [ "std" ] } -ark-relations = { version = "0.3.0", default-features = false, features = [ "std" ] } -ark-serialize = { version = "0.3.0", default-features = false } - -ark-circom = { git = "https://github.com/gakonst/ark-circom", features = ["circom-2"] } -#ark-circom = { features = ["circom-2"], path = "../../../gakonst/ark-circom" } - -# error handling -# thiserror = "1.0.26" -color-eyre = "0.5" - -# decoding of data -# hex = "0.4.3" -# byteorder = "1.4.3" - -# tracing -tracing = "0.1" -tracing-subscriber = "0.2" - -# json -serde = { version = "1.0.103", default-features = false, features = ["derive"] } -serde_json = "1.0.48" diff --git a/poseidon-tornado/README.md b/poseidon-tornado/README.md deleted file mode 100644 index 39555dd..0000000 --- a/poseidon-tornado/README.md +++ /dev/null @@ -1,15 +0,0 @@ -# Poseidon-Tornado wrapper - -`cargo run` should produce a verified proof: - -``` -Proof: Proof { a: GroupAffine { x: Fp256(BigInteger256([16555594431582187512, 832858929541131044, 7422422334369615701, 1990800952833984962])), y: Fp256(BigInteger256([1644467721434014430, 4218632298063479714, 6653830397826554436, 2216376957148540579])), infinity: false }, b: GroupAffine { x: QuadExtField { c0: Fp256(BigInteger256([9273689851960082102, 5457182187245793764, 4494028383047773695, 687780230949438867])), c1: Fp256(BigInteger256([12997553955801245812, 6091827827641861199, 16980634323548746344, 1216645975304436003])) }, y: QuadExtField { c0: Fp256(BigInteger256([7010712503187563018, 15102268349222123061, 14879829328512306542, 2444470763551517194])), c1: Fp256(BigInteger256([4642236806924837044, 921676552384439839, 10863230380949696869, 2028214605332280376])) }, infinity: false }, c: GroupAffine { x: Fp256(BigInteger256([12984346165775776486, 2185711386225701726, 2181293997313656330, 2510009027820905919])), y: Fp256(BigInteger256([7404331360498713396, 3383561268178375173, 1263588809399542185, 3239606895069814303])), infinity: false } } -``` - -## poseidon-tornado - -See: -https://github.com/ChihChengLiang/poseidon-tornado - -Some issues with mixing BigNumber radix 10 and 16 etc. The input currently used was generated with: -https://github.com/oskarth/poseidon-tornado/commit/db64ad09fdb16ad310ba395fc73520f87ad7d344 diff --git a/poseidon-tornado/resources/circom2_multiplier2.r1cs b/poseidon-tornado/resources/circom2_multiplier2.r1cs deleted file mode 100644 index e61b9b0..0000000 Binary files a/poseidon-tornado/resources/circom2_multiplier2.r1cs and /dev/null differ diff --git a/poseidon-tornado/resources/circom2_multiplier2.wasm b/poseidon-tornado/resources/circom2_multiplier2.wasm deleted file mode 100644 index 7ea487c..0000000 Binary files a/poseidon-tornado/resources/circom2_multiplier2.wasm and /dev/null differ diff --git a/poseidon-tornado/resources/withdraw.r1cs b/poseidon-tornado/resources/withdraw.r1cs deleted file mode 100644 index d5672c0..0000000 Binary files a/poseidon-tornado/resources/withdraw.r1cs and /dev/null differ diff --git a/poseidon-tornado/resources/withdraw.wasm b/poseidon-tornado/resources/withdraw.wasm deleted file mode 100644 index b29ddf7..0000000 Binary files a/poseidon-tornado/resources/withdraw.wasm and /dev/null differ diff --git a/poseidon-tornado/resources/witness-example.json b/poseidon-tornado/resources/witness-example.json deleted file mode 100644 index 16f4bc0..0000000 --- a/poseidon-tornado/resources/witness-example.json +++ /dev/null @@ -1,27 +0,0 @@ -{"root":"0x11cd2b4d61ad61dee506cac59c657e269cbbf5fbd548cd2f1d41dedaf4293748", - "nullifierHash":"0x285edfd6d2499ea9eea742d4ece6a4668efbbf93b4c2194d9e086997ad59aa4f", - "recipient":"0x3C44CdDdB6a900fa2b585dd299e03d12FA4293BC", - "relayer":"0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "fee":0, - "nullifier":"34284017061184348684424679404576688", - "pathElements":["21663839004416932945382355908790599225266501822907911457504978515578255421292", - "0x13e37f2d6cb86c78ccc1788607c2b199788c6bb0a615a21f2e7a8e88384222f8", - "0x217126fa352c326896e8c2803eec8fd63ad50cf65edfef27a41a9e32dc622765", - "0x0e28a61a9b3e91007d5a9e3ada18e1b24d6d230c618388ee5df34cacd7397eee", - "0x27953447a6979839536badc5425ed15fadb0e292e9bc36f92f0aa5cfa5013587", - "0x194191edbfb91d10f6a7afd315f33095410c7801c47175c2df6dc2cce0e3affc", - "0x1733dece17d71190516dbaf1927936fa643dc7079fc0cc731de9d6845a47741f", - "0x267855a7dc75db39d81d17f95d0a7aa572bf5ae19f4db0e84221d2b2ef999219", - "0x1184e11836b4c36ad8238a340ecc0985eeba665327e33e9b0e3641027c27620d", - "0x0702ab83a135d7f55350ab1bfaa90babd8fc1d2b3e6a7215381a7b2213d6c5ce", - "0x2eecc0de814cfd8c57ce882babb2e30d1da56621aef7a47f3291cffeaec26ad7", - "0x280bc02145c155d5833585b6c7b08501055157dd30ce005319621dc462d33b47", - "0x045132221d1fa0a7f4aed8acd2cbec1e2189b7732ccb2ec272b9c60f0d5afc5b", - "0x27f427ccbf58a44b1270abbe4eda6ba53bd6ac4d88cf1e00a13c4371ce71d366", - "0x1617eaae5064f26e8f8a6493ae92bfded7fde71b65df1ca6d5dcec0df70b2cef", - "0x20c6b400d0ea1b15435703c31c31ee63ad7ba5c8da66cec2796feacea575abca", - "0x09589ddb438723f53a8e57bdada7c5f8ed67e8fece3889a73618732965645eec", - "0x0064b6a738a5ff537db7b220f3394f0ecbd35bfd355c5425dc1166bf3236079b", - "0x095de56281b1d5055e897c3574ff790d5ee81dbc5df784ad2d67795e557c9e9f", - "0x11cf2e2887aa21963a6ec14289183efe4d4c60f14ecd3d6fe0beebdf855a9b63"], - "pathIndices":[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]} diff --git a/poseidon-tornado/src/ffi.rs b/poseidon-tornado/src/ffi.rs deleted file mode 100644 index 4ff6e41..0000000 --- a/poseidon-tornado/src/ffi.rs +++ /dev/null @@ -1,77 +0,0 @@ -use crate::public::PoseidonTornado; -use std::slice; - -/// Buffer struct is taken from -/// https://github.com/celo-org/celo-threshold-bls-rs/blob/master/crates/threshold-bls-ffi/src/ffi.rs -/// -/// Also heavily inspired by https://github.com/kilic/rln/blob/master/src/ffi.rs - -#[repr(C)] -#[derive(Clone, Debug, PartialEq)] -pub struct Buffer { - pub ptr: *const u8, - pub len: usize, -} - -impl From<&[u8]> for Buffer { - fn from(src: &[u8]) -> Self { - Self { - ptr: &src[0] as *const u8, - len: src.len(), - } - } -} - -impl<'a> From<&Buffer> for &'a [u8] { - fn from(src: &Buffer) -> &'a [u8] { - unsafe { slice::from_raw_parts(src.ptr, src.len) } - } -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[no_mangle] -pub extern "C" fn new_circuit(ctx: *mut *mut PoseidonTornado) -> bool { - println!("multiplier ffi: new"); - let mul = PoseidonTornado::new(); - - unsafe { *ctx = Box::into_raw(Box::new(mul)) }; - - true -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[no_mangle] -pub extern "C" fn prove(ctx: *const PoseidonTornado, output_buffer: *mut Buffer) -> bool { - println!("multiplier ffi: prove"); - let mul = unsafe { &*ctx }; - let mut output_data: Vec = Vec::new(); - - match mul.prove(&mut output_data) { - Ok(proof_data) => proof_data, - Err(_) => return false, - }; - unsafe { *output_buffer = Buffer::from(&output_data[..]) }; - std::mem::forget(output_data); - true -} - -#[allow(clippy::not_unsafe_ptr_arg_deref)] -#[no_mangle] -pub extern "C" fn verify( - ctx: *const PoseidonTornado, - proof_buffer: *const Buffer, - result_ptr: *mut u32, -) -> bool { - println!("multiplier ffi: verify"); - let mul = unsafe { &*ctx }; - let proof_data = <&[u8]>::from(unsafe { &*proof_buffer }); - if match mul.verify(proof_data) { - Ok(verified) => verified, - Err(_) => return false, - } { - unsafe { *result_ptr = 0 }; - } else { - unsafe { *result_ptr = 1 }; - }; - true -} diff --git a/poseidon-tornado/src/lib.rs b/poseidon-tornado/src/lib.rs deleted file mode 100644 index 767579a..0000000 --- a/poseidon-tornado/src/lib.rs +++ /dev/null @@ -1,2 +0,0 @@ -pub mod ffi; -pub mod public; diff --git a/poseidon-tornado/src/main.rs b/poseidon-tornado/src/main.rs deleted file mode 100644 index caf9ca1..0000000 --- a/poseidon-tornado/src/main.rs +++ /dev/null @@ -1,176 +0,0 @@ -use ark_circom::{CircomBuilder, CircomConfig}; -use ark_std::rand::thread_rng; -use color_eyre::Result; - -use ark_bn254::Bn254; -use ark_groth16::{ - create_random_proof, generate_random_parameters, prepare_verifying_key, verify_proof, -}; - -use num_bigint::BigInt; - -// Tracing -use ark_relations::r1cs::{ConstraintLayer, ConstraintTrace, TracingMode}; -//use tracing::{event, span, Level}; -use tracing_subscriber::layer::SubscriberExt; - -// JSON -use serde::Deserialize; -//use serde_json; - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct WitnessInput { - root: String, - nullifier_hash: String, - recipient: String, - relayer: String, - //fee: String, - fee: i32, - nullifier: String, - path_elements: Vec, - path_indices: Vec, -} - -// Poseidon-tornado -fn groth16_proof_example() -> Result<()> { - // Tracing to help with debugging - let mut layer = ConstraintLayer::default(); - layer.mode = TracingMode::OnlyConstraints; - let subscriber = tracing_subscriber::Registry::default().with(layer); - let _guard = tracing::subscriber::set_default(subscriber); - - let trace = ConstraintTrace::capture(); - println!("Trace is: {:?}", trace); - - let cfg = CircomConfig::::new("./resources/withdraw.wasm", "./resources/withdraw.r1cs")?; - - // Test - let trace = ConstraintTrace::capture(); - println!("Trace is: {:?}", trace); - - // From poseidon-tornado JSON witness - // Input generated with https://github.com/oskarth/poseidon-tornado/commit/db64ad09fdb16ad310ba395fc73520f87ad7d344 - // With nullifier set to 0 - let input_json_str = r#" -{ - "root": "17777834528943231885798890273562835075271930126129561600279382876922601684948", - "nullifierHash": "8506691148847834795277894036216352001616813487121834991716343668271924769133", - "recipient": "344073830386746567427978432078835137280280269756", - "relayer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "fee": 0, - "nullifier": "0", - "pathElements": [ - "21663839004416932945382355908790599225266501822907911457504978515578255421292", - "8995896153219992062710898675021891003404871425075198597897889079729967997688", - "15126246733515326086631621937388047923581111613947275249184377560170833782629", - "6404200169958188928270149728908101781856690902670925316782889389790091378414", - "17903822129909817717122288064678017104411031693253675943446999432073303897479", - "11423673436710698439362231088473903829893023095386581732682931796661338615804", - "10494842461667482273766668782207799332467432901404302674544629280016211342367", - "17400501067905286947724900644309270241576392716005448085614420258732805558809", - "7924095784194248701091699324325620647610183513781643345297447650838438175245", - "3170907381568164996048434627595073437765146540390351066869729445199396390350", - "21224698076141654110749227566074000819685780865045032659353546489395159395031", - "18113275293366123216771546175954550524914431153457717566389477633419482708807", - "1952712013602708178570747052202251655221844679392349715649271315658568301659", - "18071586466641072671725723167170872238457150900980957071031663421538421560166", - "9993139859464142980356243228522899168680191731482953959604385644693217291503", - "14825089209834329031146290681677780462512538924857394026404638992248153156554", - "4227387664466178643628175945231814400524887119677268757709033164980107894508", - "177945332589823419436506514313470826662740485666603469953512016396504401819", - "4236715569920417171293504597566056255435509785944924295068274306682611080863", - "8055374341341620501424923482910636721817757020788836089492629714380498049891" - ], - "pathIndices": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} -"#; - - let witness_input: WitnessInput = - serde_json::from_str(input_json_str).expect("JSON was not well-formatted"); - - println!("Witness input JSON: {:?}", witness_input); - - let mut builder = CircomBuilder::new(cfg); - - builder.push_input( - "root", - BigInt::parse_bytes(witness_input.root.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "nullifierHash", - BigInt::parse_bytes(witness_input.nullifier_hash.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "recipient", - BigInt::parse_bytes(witness_input.recipient.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "relayer", - BigInt::parse_bytes( - witness_input.relayer.strip_prefix("0x").unwrap().as_bytes(), - 16, - ) - .unwrap(), - ); - - // XXX - builder.push_input( - "fee", - witness_input.fee, //BigInt::parse_bytes(witness_input.fee.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "nullifier", - BigInt::parse_bytes(witness_input.nullifier.as_bytes(), 10).unwrap(), - ); - - for v in witness_input.path_elements.iter() { - builder.push_input( - "pathElements", - BigInt::parse_bytes(v.as_bytes(), 10).unwrap(), - ); - } - - for v in witness_input.path_indices.iter() { - builder.push_input("pathIndices", BigInt::from(*v)); - } - - println!("Builder input:\n {:#?}", builder.inputs); - - // create an empty instance for setting it up - let circom = builder.setup(); - - let mut rng = thread_rng(); - let params = generate_random_parameters::(circom, &mut rng)?; - - let circom = builder.build()?; - - let inputs = circom.get_public_inputs().unwrap(); - - println!("Public inputs {:#?} ", inputs); - - let proof = create_random_proof(circom, ¶ms, &mut rng)?; - - println!("Proof: {:?}", proof); - - let pvk = prepare_verifying_key(¶ms.vk); - - let verified = verify_proof(&pvk, &proof, &inputs)?; - - assert!(verified); - - Ok(()) -} - -fn main() { - println!("tornado-poseidon example proof"); - - // Tornado-core - match groth16_proof_example() { - Ok(_) => println!("Success"), - Err(_) => println!("Error"), - } -} diff --git a/poseidon-tornado/src/public.rs b/poseidon-tornado/src/public.rs deleted file mode 100644 index 31f45f1..0000000 --- a/poseidon-tornado/src/public.rs +++ /dev/null @@ -1,204 +0,0 @@ -use ark_circom::{CircomBuilder, CircomCircuit, CircomConfig}; -use ark_std::rand::thread_rng; - -use ark_bn254::Bn254; -use ark_groth16::{ - create_random_proof as prove, generate_random_parameters, prepare_verifying_key, verify_proof, - Proof, ProvingKey, -}; -use ark_serialize::{CanonicalDeserialize, CanonicalSerialize}; -// , SerializationError}; - -use num_bigint::BigInt; - -use std::io::{self, Read, Write}; - -use serde::Deserialize; - -pub struct PoseidonTornado { - circom: CircomCircuit, - params: ProvingKey, -} - -#[derive(Debug, Deserialize)] -#[serde(rename_all = "camelCase")] -struct WitnessInput { - root: String, - nullifier_hash: String, - recipient: String, - relayer: String, - //fee: String, - fee: i32, - nullifier: String, - path_elements: Vec, - path_indices: Vec, -} - -// TODO This should use poseidon-tornado stuff in main.rs for proper example - -impl PoseidonTornado { - // TODO Break this apart here - pub fn new() -> PoseidonTornado { - let cfg = - CircomConfig::::new("./resources/withdraw.wasm", "./resources/withdraw.r1cs") - .unwrap(); - - // From poseidon-tornado JSON witness - // Input generated with https://github.com/oskarth/poseidon-tornado/commit/db64ad09fdb16ad310ba395fc73520f87ad7d344 - // With nullifier set to 0 - let input_json_str = r#" -{ - "root": "17777834528943231885798890273562835075271930126129561600279382876922601684948", - "nullifierHash": "8506691148847834795277894036216352001616813487121834991716343668271924769133", - "recipient": "344073830386746567427978432078835137280280269756", - "relayer": "0x70997970C51812dc3A010C7d01b50e0d17dc79C8", - "fee": 0, - "nullifier": "0", - "pathElements": [ - "21663839004416932945382355908790599225266501822907911457504978515578255421292", - "8995896153219992062710898675021891003404871425075198597897889079729967997688", - "15126246733515326086631621937388047923581111613947275249184377560170833782629", - "6404200169958188928270149728908101781856690902670925316782889389790091378414", - "17903822129909817717122288064678017104411031693253675943446999432073303897479", - "11423673436710698439362231088473903829893023095386581732682931796661338615804", - "10494842461667482273766668782207799332467432901404302674544629280016211342367", - "17400501067905286947724900644309270241576392716005448085614420258732805558809", - "7924095784194248701091699324325620647610183513781643345297447650838438175245", - "3170907381568164996048434627595073437765146540390351066869729445199396390350", - "21224698076141654110749227566074000819685780865045032659353546489395159395031", - "18113275293366123216771546175954550524914431153457717566389477633419482708807", - "1952712013602708178570747052202251655221844679392349715649271315658568301659", - "18071586466641072671725723167170872238457150900980957071031663421538421560166", - "9993139859464142980356243228522899168680191731482953959604385644693217291503", - "14825089209834329031146290681677780462512538924857394026404638992248153156554", - "4227387664466178643628175945231814400524887119677268757709033164980107894508", - "177945332589823419436506514313470826662740485666603469953512016396504401819", - "4236715569920417171293504597566056255435509785944924295068274306682611080863", - "8055374341341620501424923482910636721817757020788836089492629714380498049891" - ], - "pathIndices": [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]} -"#; - - let witness_input: WitnessInput = - serde_json::from_str(input_json_str).expect("JSON was not well-formatted"); - - println!("Witness input JSON: {:?}", witness_input); - - let mut builder = CircomBuilder::new(cfg); - - builder.push_input( - "root", - BigInt::parse_bytes(witness_input.root.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "nullifierHash", - BigInt::parse_bytes(witness_input.nullifier_hash.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "recipient", - BigInt::parse_bytes(witness_input.recipient.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "relayer", - BigInt::parse_bytes( - witness_input.relayer.strip_prefix("0x").unwrap().as_bytes(), - 16, - ) - .unwrap(), - ); - - // XXX - builder.push_input( - "fee", - witness_input.fee, //BigInt::parse_bytes(witness_input.fee.as_bytes(), 10).unwrap(), - ); - - builder.push_input( - "nullifier", - BigInt::parse_bytes(witness_input.nullifier.as_bytes(), 10).unwrap(), - ); - - for v in witness_input.path_elements.iter() { - builder.push_input( - "pathElements", - BigInt::parse_bytes(v.as_bytes(), 10).unwrap(), - ); - } - - for v in witness_input.path_indices.iter() { - builder.push_input("pathIndices", BigInt::from(*v)); - } - - println!("Builder input:\n {:#?}", builder.inputs); - - // create an empty instance for setting it up - let circom = builder.setup(); - - let mut rng = thread_rng(); - let params = generate_random_parameters::(circom, &mut rng).unwrap(); - - let circom = builder.build().unwrap(); - - let inputs = circom.get_public_inputs().unwrap(); - - println!("Public inputs {:#?} ", inputs); - - PoseidonTornado { circom, params } - } - - // TODO Input Read - pub fn prove(&self, result_data: W) -> io::Result<()> { - let mut rng = thread_rng(); - - // XXX: There's probably a better way to do this - let circom = self.circom.clone(); - let params = self.params.clone(); - - let proof = prove(circom, ¶ms, &mut rng).unwrap(); - - // XXX: Unclear if this is different from other serialization(s) - let _ = proof.serialize(result_data).unwrap(); - - Ok(()) - } - - pub fn verify(&self, input_data: R) -> io::Result { - let proof = Proof::deserialize(input_data).unwrap(); - - let pvk = prepare_verifying_key(&self.params.vk); - - // XXX Part of input data? - let inputs = self.circom.get_public_inputs().unwrap(); - - let verified = verify_proof(&pvk, &proof, &inputs).unwrap(); - - Ok(verified) - } -} - -impl Default for PoseidonTornado { - fn default() -> Self { - Self::new() - } -} - -#[test] -fn poseidon_tornado_proof() { - let pt = PoseidonTornado::new(); - //let inputs = pt.circom.get_public_inputs().unwrap(); - - let mut output_data: Vec = Vec::new(); - let _ = pt.prove(&mut output_data); - - let proof_data = &output_data[..]; - - // XXX Pass as arg? - //let pvk = prepare_verifying_key(&pt.params.vk); - - let verified = pt.verify(proof_data).unwrap(); - - assert!(verified); -}