newton-core 0.4.16

newton protocol core sdk
#![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;

/// Proves the policy evaluation result using SP1
/// # Arguments
/// * `elf` - The ELF binary to prove
/// * `task` - The task to prove
/// * `task_response` - The task response to prove
/// * `entrypoint` - The entrypoint to prove
/// # Returns
/// A `Result` containing the proof, or an error if the proof fails
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;

    // v6 setup is async and yields only the proving key; the verifying key is derived from it.
    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));

    // Wait for proof completion. 300s ceiling: rego proofs are light, but the Succinct Prover
    // Network can run slow under load on the Reserved strategy (v5 observed ~90s), so leave headroom.
    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,
    })
}