diff --git a/plonky2x/core/src/backend/function/mod.rs b/plonky2x/core/src/backend/function/mod.rs index 3eb91263..ecc726ab 100644 --- a/plonky2x/core/src/backend/function/mod.rs +++ b/plonky2x/core/src/backend/function/mod.rs @@ -128,6 +128,142 @@ impl Plonky2xFunction for C { } } + // fn prove< + // InnerParameters: PlonkParameters, + // OuterParameters: PlonkParameters, + // const D: usize, + // >( + // args: ProveArgs, + // request: ProofRequest, + // ) where + // >::Hasher: + // AlgebraicHasher, + // OuterParameters::Config: Serialize, + // { + // // If the request is of type bytes and the wrapper path is not empty, then we need to + // // start the gnark wrapper process. + // let gnark_wrapper_process = if let ProofRequest::Bytes(_) = request { + // if !args.wrapper_path.is_empty() { + // let child_process = std::process::Command::new( + // path::Path::new(&args.wrapper_path).join("verifier"), + // ) + // .arg("-prove") + // .arg("-data") + // .arg(path::Path::new(&args.wrapper_path)) + // .stdout(std::process::Stdio::inherit()) + // .stderr(std::process::Stdio::inherit()) + // .stdin(std::process::Stdio::piped()) + // .spawn() + // .expect("Failed to start gnark wrapper process"); + // Some(child_process) + // } else { + // None + // } + // } else { + // None + // }; + + // let mut generator_registry = HintRegistry::new(); + // let mut gate_registry = GateRegistry::new(); + // C::register_generators::(&mut generator_registry); + // C::register_gates::(&mut gate_registry); + + // let mut path = match request { + // ProofRequest::Bytes(_) => { + // format!("{}/main.circuit", args.build_dir) + // } + // ProofRequest::Elements(ref request) => { + // format!("{}/{}.circuit", args.build_dir, request.data.circuit_id) + // } + // ProofRequest::RecursiveProofs(ref request) => { + // format!("{}/{}.circuit", args.build_dir, request.data.circuit_id) + // } + // _ => todo!(), + // }; + // if fs::metadata(&path).is_err() { + // path = format!("{}/main.circuit", args.build_dir); + // } + + // info!("Loading circuit from {}...", path); + // let circuit = + // CircuitBuild::::load(&path, &gate_registry, &generator_registry) + // .unwrap(); + // info!("Successfully loaded circuit."); + + // let input = request.input(); + // let (proof, output) = circuit.prove(&input); + // info!( + // "Successfully generated proof, wrapping proof with {}", + // args.wrapper_path + // ); + + // if let PublicInput::Bytes(input_bytes) = input { + // info!("Input Bytes: 0x{}", hex::encode(input_bytes)); + // } + + // if let PublicOutput::Bytes(output_bytes) = output { + // // It's quite fast (~5-10 seconds) to rebuild the wrapped circuit. Because of this we + // // choose to rebuild here instead of loading from disk. + // info!("Output Bytes: 0x{}", hex::encode(output_bytes.clone())); + // let wrapped_circuit = + // WrappedCircuit::::build(circuit); + // let wrapped_proof = wrapped_circuit.prove(&proof).expect("failed to wrap proof"); + // wrapped_proof + // .save("wrapped") + // .expect("failed to save wrapped proof"); + + // // The gnark_wrapper_process should have been started. + // let mut gnark_wrapper_process = gnark_wrapper_process.unwrap(); + // let mut stdin_opt = None; + // while stdin_opt.is_none() { + // stdin_opt = match gnark_wrapper_process.stdin.as_mut() { + // Some(stdin) => { + // info!("Got stdin of child process"); + // Some(stdin) + // } + // None => { + // info!("Failed to open stdin of gnark wrapper. Retrying..."); + // std::thread::sleep(std::time::Duration::from_secs(1)); + // None + // } + // }; + // } + + // let stdin = stdin_opt.unwrap(); + // stdin + // .write_all(b"wrapped\n") + // .expect("Failed to write to stdin"); + // let verifier_output = gnark_wrapper_process + // .wait_with_output() + // .expect("failed to execute process"); + + // if !verifier_output.status.success() { + // panic!("verifier failed"); + // } + + // // Read result from gnark verifier. + // let file = std::fs::File::open("proof.json").unwrap(); + // let rdr = std::io::BufReader::new(file); + // let result_data = + // serde_json::from_reader::, BytesResultData>(rdr).unwrap(); + + // // Write full result with output bytes to output.json. + // let result: ProofResult = + // ProofResult::from_bytes(result_data.proof, output_bytes); + // let json = serde_json::to_string_pretty(&result).unwrap(); + // info!("output.json:\n{}", json); + // let mut file = File::create("output.json").unwrap(); + // file.write_all(json.as_bytes()).unwrap(); + // info!("Successfully saved full result to disk at output.json."); + // } else { + // let result = ProofResult::from_proof_output(proof, output); + // let json = serde_json::to_string_pretty(&result).unwrap(); + // let mut file = File::create("output.json").unwrap(); + // file.write_all(json.as_bytes()).unwrap(); + // info!("Successfully saved proof to disk at output.json."); + // } + // } + fn prove< InnerParameters: PlonkParameters, OuterParameters: PlonkParameters, @@ -140,130 +276,70 @@ impl Plonky2xFunction for C { AlgebraicHasher, OuterParameters::Config: Serialize, { + // Initialize the registry for any custom generators and gates let mut generator_registry = HintRegistry::new(); let mut gate_registry = GateRegistry::new(); C::register_generators::(&mut generator_registry); C::register_gates::(&mut gate_registry); - let mut path = match request { - ProofRequest::Bytes(_) => { - format!("{}/main.circuit", args.build_dir) - } + // Determine the circuit path based on the request type + let circuit_path = match request { + ProofRequest::Bytes(_) => format!("{}/main.circuit", args.build_dir), ProofRequest::Elements(ref request) => { format!("{}/{}.circuit", args.build_dir, request.data.circuit_id) } ProofRequest::RecursiveProofs(ref request) => { format!("{}/{}.circuit", args.build_dir, request.data.circuit_id) } - _ => todo!(), + _ => panic!("Unhandled proof request type"), }; - if fs::metadata(&path).is_err() { - path = format!("{}/main.circuit", args.build_dir); - } - info!("Loading circuit from {}...", path); - let circuit = - CircuitBuild::::load(&path, &gate_registry, &generator_registry) - .unwrap(); - info!("Successfully loaded circuit."); + // Ensure the circuit file exists, otherwise default to main.circuit + let circuit_path = if fs::metadata(&circuit_path).is_err() { + format!("{}/main.circuit", args.build_dir) + } else { + circuit_path + }; + + // Load the circuit from the specified path + info!("Loading circuit from {}...", circuit_path); + let circuit = CircuitBuild::::load( + &circuit_path, + &gate_registry, + &generator_registry, + ) + .expect("Failed to load circuit"); + // Generate the proof for the loaded circuit let input = request.input(); let (proof, output) = circuit.prove(&input); - - if let PublicInput::Bytes(input_bytes) = input { - info!("Input Bytes: 0x{}", hex::encode(input_bytes)); - } - - if let PublicOutput::Bytes(output_bytes) = output { - // It's quite fast (~5-10 seconds) to rebuild the wrapped circuit. Because of this we - // choose to rebuild here instead of loading from disk. - info!("Output Bytes: 0x{}", hex::encode(output_bytes.clone())); - let wrapped_circuit = - WrappedCircuit::::build(circuit); - let wrapped_proof = wrapped_circuit.prove(&proof).expect("failed to wrap proof"); - wrapped_proof - .save("wrapped") - .expect("failed to save wrapped proof"); - - println!( - "Starting gnark wrapper process with command: {:?}", - path::Path::new(&args.wrapper_path).join("verifier") - ); - println!( - "Arguments: -prove -data {}", - path::Path::new(&args.wrapper_path).display() - ); - - let wrapped_circuit_path = format!("{}/wrapped", args.build_dir); - wrapped_proof - .save(wrapped_circuit_path) - .expect("failed to save wrapped proof"); - - let gnark_wrapper_process = if let ProofRequest::Bytes(_) = request { - let child_process = std::process::Command::new( - path::Path::new(&args.wrapper_path).join("verifier"), - ) + info!( + "Successfully generated proof: {:?} output: {:?}", + proof, output + ); + + if !args.wrapper_path.is_empty() { + // Construct the command to execute the wrapper_circuit + let child_process = std::process::Command::new(&args.wrapper_path) .arg("-prove") .arg("-data") .arg(path::Path::new(&args.wrapper_path)) .arg("-circuit") - .arg("wrapped") - .stdout(std::process::Stdio::piped()) - .stderr(std::process::Stdio::piped()) - .stdin(std::process::Stdio::piped()) + .arg(circuit_path) + .stdout(std::process::Stdio::inherit()) + .stderr(std::process::Stdio::inherit()) .spawn() .expect("Failed to start gnark wrapper process"); - Some(child_process) - } else { - None - }; - - // The gnark_wrapper_process should have been started. - let mut gnark_wrapper_process = gnark_wrapper_process.unwrap(); - let mut stdin_opt = None; - while stdin_opt.is_none() { - stdin_opt = match gnark_wrapper_process.stdin.as_mut() { - Some(stdin) => { - info!("Got stdin of child process"); - Some(stdin) - } - None => { - info!("Failed to open stdin of gnark wrapper. Retrying..."); - std::thread::sleep(std::time::Duration::from_secs(1)); - None - } - }; - } - let verifier_output = gnark_wrapper_process - .stdout - .as_mut() - .expect("Failed to open stdout of gnark wrapper"); - - if !verifier_output.status.success() { - panic!("verifier failed"); + // Wait for the wrapper_circuit process to complete + let output = child_process + .wait_with_output() + .expect("Failed to wait on gnark wrapper process"); + if !output.status.success() { + panic!("Wrapper process failed"); } - - // Read result from gnark verifier. - let file = std::fs::File::open("proof.json").unwrap(); - let rdr = std::io::BufReader::new(file); - let result_data = - serde_json::from_reader::, BytesResultData>(rdr).unwrap(); - - // Write full result with output bytes to output.json. - let result: ProofResult = - ProofResult::from_bytes(result_data.proof, output_bytes); - let json = serde_json::to_string_pretty(&result).unwrap(); - info!("output.json:\n{}", json); - let mut file = File::create("output.json").unwrap(); - file.write_all(json.as_bytes()).unwrap(); - info!("Successfully saved full result to disk at output.json."); } else { - let result = ProofResult::from_proof_output(proof, output); - let json = serde_json::to_string_pretty(&result).unwrap(); - let mut file = File::create("output.json").unwrap(); - file.write_all(json.as_bytes()).unwrap(); - info!("Successfully saved proof to disk at output.json."); + panic!("Wrapper path is empty, cannot proceed with verification."); } } @@ -309,7 +385,7 @@ contract FunctionVerifier is IFunctionVerifier, Verifier { function verify(bytes32 _inputHash, bytes32 _outputHash, bytes memory _proof) external view returns (bool) { (uint256[8] memory proof) = abi.decode(_proof, (uint256[8])); - uint256[3] memory input; + uint256[4] memory input; input[0] = uint256(CIRCUIT_DIGEST); input[1] = uint256(_inputHash) & ((1 << 253) - 1); input[2] = uint256(_outputHash) & ((1 << 253) - 1);