processor

The processor is the on-chain aspect of the IC-ADC. It is responsible for receiving data from an off-chain orchestrator node, verifying provided TLS proofs, and processing this data for destination Canisters within the Internet Computer.

Inter-Canister Call to Verity Verifier

In the processor/ic/src/sources/mod.rs file, the function request_proof_verification makes an inter-canister call to the ic/managed/verifier. This call is crucial for obtaining verified or decrypted proofs from the managed verifier canister.

/// Request verification from the managed verifier response
pub async fn request_proof_verification(
    stringified_proofs: &Vec<String>,
    notary_pubkey: &String,
) -> Vec<ProofResponse> {
    let verifier_canister = state::get_verifier_canister().unwrap();

    // make a request to the managed verifier canister
    // to get a response which would contain the verified/decrypted proofs sent
    let (response,): (Vec<ProofResponse>,) = ic_cdk::call(
        verifier_canister,
        "verify_proof_async",
        (stringified_proofs, notary_pubkey),
    )
    .await
    .unwrap();

    response
}

The function uses the ic_cdk::call method to communicate with the verifier canister, passing the stringified proofs and the notary public key as arguments. This interaction is a key part of the Verity DP framework, enabling the Internet Computer to verify proofs asynchronously.

In a parent function call get_token_price, we simply parses the response proofs to obtain the values.

There is no subsequent proof after the request_proof_verification call. This is because all of this computation is occurring on-chain, within the IC.
// Provided a token and a notary public key for the notary used to generate the proofs attached to the tokens
// verify/decrypt the proofs and come to a concensus on the token price
pub async fn get_token_price(token: &Token, notary_pubkey: &String) -> anyhow::Result<f64> {
    // get the proofs in a stringified form
    let proof_types = token.proofs.as_ref().unwrap();
    let stringified_proofs: Vec<String> = proof_types
        .iter()
        .map(|pt: &ProofTypes| pt.to_string())
        .collect();

    // request proof response from verification canister
    let verification_response_proofs =
        request_proof_verification(&stringified_proofs, notary_pubkey).await;

    // parse the proof response based on the corresponding proof type
    // to get the price in the response of the http response body of the verified request
    // use the proof type to parse the json as either a pyth or redstone proof
    let asset_price = get_asset_price_from_proofs(proof_types, &verification_response_proofs);

    asset_price
}

orchestrator

Verity Client Usage

The verity-client module is used in the orchestrator/src/helpers/verity.rs file to create a VerityClient for interfacing with a Verity Prover.

use verity_client::client::{VerityClient, VerityClientConfig};

use crate::config::Config;

pub const DEFAULT_PROVER_URL: &str = "http://127.0.0.1:8080";

pub fn get_verity_client() -> VerityClient {
    let config = Config::env();

    let verity_config = VerityClientConfig {
        prover_url: config.prover_url,
    };

    VerityClient::new(verity_config)
}

In a parent function, the verity_client is used similarly to Rust’s reqwest library:

impl PricingDataSource for Pyth {
    fn new() -> Self {
        Self {}
    }

    async fn get_url(ticker: String) -> Result<String> {
        let ticker_id = Self::get_ticker_id(ticker).await?;
        Ok(format!(
            "https://hermes.pyth.network/api/latest_price_feeds?ids[]={}",
            ticker_id
        ))
    }

    async fn get_proof(ticker: String) -> Result<ProofTypes> {
        // construct the request URL
        let request_url = Self::get_url(ticker).await?;
        let verity_client = get_verity_client();

        // get the proof using the verity client
        let response = verity_client.get(&request_url).send().await?;

        // check for a succesfull and valid response
        let http_response_string = response.subject.text().await?;
        Self::validate_response(http_response_string).await?;

        return Ok(ProofTypes::Pyth(response.proof));
    }

Conclusion

These references show where the Verity DP modules are integrated within the processor and orchestrator folders. The inter-canister call to the Verity Verifier and the use of the Verity Client are essential components of the Verity DP integration, ensuring secure and efficient data processing and verification.