#![cfg(feature = "rpc")]
use crate::{
newton_prover_task_manager::INewtonProverTaskManager::{Task, TaskResponse},
zk::Proof,
};
use sp1_sdk::{
network::FulfillmentStrategy, Elf, HashableKey, ProveRequest, Prover, ProverClient, ProvingKey, SP1Stdin,
};
use std::time::Duration;
pub async fn prove(elf: Vec<u8>, task: Task, task_response: TaskResponse, entrypoint: String) -> eyre::Result<Proof> {
tracing::info!("Using Sp1 proof type");
crate::config::dotenv::init().unwrap();
let mut stdin = SP1Stdin::new();
stdin.write(&task);
stdin.write(&task_response);
stdin.write(&entrypoint);
tracing::info!("sp1 client: {}", crate::config::dotenv::get::<String>("SP1_PROVER"));
let client = ProverClient::builder()
.network()
.private_key(&crate::config::dotenv::get::<String>("NETWORK_PRIVATE_KEY"))
.build()
.await;
let pk = client
.setup(Elf::from(elf))
.await
.map_err(|e| eyre::eyre!("SP1 setup failed: {e}"))?;
let vk = pk.verifying_key().clone();
tracing::info!("requesting proof {}", vk.bytes32().to_string().as_str());
let request_id = client
.prove(&pk, stdin)
.groth16()
.strategy(FulfillmentStrategy::Reserved)
.request()
.await
.map_err(|e| eyre::eyre!("SP1 proof request failed: {e}"))?;
tracing::info!("Prover Request ID: {}", crate::hex!(request_id));
let proof = client
.wait_proof(request_id, Some(Duration::from_secs(300)), None)
.await
.map_err(|e| eyre::eyre!("SP1 proof generation failed: {e}"))?;
let journal = proof.public_values.as_slice();
tracing::info!("Execution Output (journal): {}", crate::hex!(journal));
tracing::info!("VK: {}", vk.bytes32().to_string().as_str());
tracing::info!("Proof: {}", crate::hex!(proof.bytes()));
Ok(Proof::Sp1 {
journal: journal.to_vec(),
vk,
proof,
request_id,
})
}