Skip to content

Commit

Permalink
feat!: support querying at particular blocks
Browse files Browse the repository at this point in the history
Currently, both the rust and javascript clients perform queries at the
latest block. We want to be able to perform queries at older blocks too.
This is especially important for the chainlink use case, as chainlink's
DON will perform the same query multiple times, expecting the same
results from each run. To this end, this changes both clients and their
underlying functions to accept an optional block hash.
  • Loading branch information
tlovell-sxt committed Nov 25, 2024
1 parent ccd8aad commit e500875
Show file tree
Hide file tree
Showing 6 changed files with 49 additions and 21 deletions.
5 changes: 5 additions & 0 deletions crates/proof-of-sql-sdk/examples/cli/args.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use clap::Parser;
use subxt::utils::H256;
use sxt_proof_of_sql_sdk::{PostprocessingLevel, SxTClient};

/// Struct to define and parse command-line arguments for Proof of SQL Client.
Expand Down Expand Up @@ -68,6 +69,10 @@ pub struct SdkArgs {
)]
pub table_ref: String,

/// SxT chain block hash to perform the query at.
#[arg(long)]
pub block_hash: Option<H256>,

/// Path to the verifier setup binary file
///
/// Specifies the path to the `verifier_setup.bin` file required for verification.
Expand Down
2 changes: 1 addition & 1 deletion crates/proof-of-sql-sdk/examples/cli/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ async fn main() -> Result<(), Box<dyn core::error::Error>> {

// Execute the query and verify the result
let result = client
.query_and_verify(&args.query, &args.table_ref)
.query_and_verify(&args.query, &args.table_ref, args.block_hash)
.await?;

// Print the result of the query
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ async fn count_table(
let uppercased_table_ref = table_ref.to_uppercase();
let query = format!("SELECT COUNT(*) FROM {uppercased_table_ref}");
let table = client
.query_and_verify(&query, &uppercased_table_ref)
.query_and_verify(&query, &uppercased_table_ref, None)
.await?;
assert_eq!(table.num_columns(), 1);
assert_eq!(table.num_rows(), 1);
Expand Down
23 changes: 17 additions & 6 deletions crates/proof-of-sql-sdk/src/client.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::{get_access_token, query_commitments};
use crate::{get_access_token, query_commitments, substrate::SxtConfig};
use clap::ValueEnum;
use proof_of_sql::{
base::database::{OwnedTable, TableRef},
Expand All @@ -7,6 +7,7 @@ use proof_of_sql::{
};
use reqwest::Client;
use std::path::Path;
use subxt::{blocks::BlockRef, Config};
use sxt_proof_of_sql_sdk_local::{
plan_prover_query_dory, prover::ProverResponse, verify_prover_response,
};
Expand Down Expand Up @@ -74,23 +75,33 @@ impl SxTClient {
self
}

/// Query and verify a SQL query
/// Query and verify a SQL query at the given SxT block.
///
/// Run a SQL query and verify the result using Dynamic Dory.
pub async fn query_and_verify(
///
/// If `block_ref` is `None`, the latest block is used.
pub async fn query_and_verify<BR>(
&self,
query: &str,
table: &str,
) -> Result<OwnedTable<DoryScalar>, Box<dyn core::error::Error>> {
block_ref: Option<BR>,
) -> Result<OwnedTable<DoryScalar>, Box<dyn core::error::Error>>
where
BR: Into<BlockRef<<SxtConfig as Config>::Hash>> + Clone,
{
// Parse table_ref into TableRef struct
let table_ref = TableRef::new(table.parse()?);

// Load verifier setup
let verifier_setup_path = Path::new(&self.verifier_setup);
let verifier_setup = VerifierSetup::load_from_file(verifier_setup_path)?;
// Accessor setup
let accessor =
query_commitments(&[table_ref.resource_id()], &self.substrate_node_url).await?;
let accessor = query_commitments(
&[table_ref.resource_id()],
&self.substrate_node_url,
block_ref,
)
.await?;

let (prover_query, query_expr) = plan_prover_query_dory(query, &accessor)?;

Expand Down
28 changes: 19 additions & 9 deletions crates/proof-of-sql-sdk/src/substrate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use proof_of_sql::{
proof_primitive::dory::DynamicDoryCommitment,
};
use proof_of_sql_parser::ResourceId;
use subxt::{OnlineClient, PolkadotConfig};
use subxt::{blocks::BlockRef, Config, OnlineClient, PolkadotConfig};
use sxt_proof_of_sql_sdk_local::{
resource_id_to_table_id,
sxt_chain_runtime::api::{
Expand All @@ -19,28 +19,38 @@ use sxt_proof_of_sql_sdk_local::{
};

/// Use the standard PolkadotConfig
type SxtConfig = PolkadotConfig;
pub type SxtConfig = PolkadotConfig;

/// Query the commitments pallet to find which commitments
pub async fn query_commitments(
/// Get the commitments for the given tables at the given SxT block.
///
/// If `block_ref` is `None`, the latest block is used.
pub async fn query_commitments<BR>(
resource_ids: &[ResourceId],
url: &str,
) -> Result<QueryCommitments<DynamicDoryCommitment>, Box<dyn core::error::Error>> {
block_ref: Option<BR>,
) -> Result<QueryCommitments<DynamicDoryCommitment>, Box<dyn core::error::Error>>
where
BR: Into<BlockRef<<SxtConfig as Config>::Hash>> + Clone,
{
let api = OnlineClient::<SxtConfig>::from_insecure_url(url).await?;

// Create a collection of futures
let futures = resource_ids.iter().map(|id| {
let api = api.clone();
let id = *id;
let block_ref = block_ref.clone();
async move {
let table_id = resource_id_to_table_id(&id);
let commitments_query = storage()
.commitments()
.commitment_storage_map(&table_id, &CommitmentScheme::DynamicDory);
let table_commitment_bytes: TableCommitmentBytes = api
.storage()
.at_latest()
.await?

let storage_at_block_ref = match block_ref {
Some(block_ref) => api.storage().at(block_ref),
None => api.storage().at_latest().await?,
};

let table_commitment_bytes: TableCommitmentBytes = storage_at_block_ref
.fetch(&commitments_query)
.await?
.ok_or("Commitment not found")?;
Expand Down
10 changes: 6 additions & 4 deletions node/src/index_tail.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,9 @@ export class SxTClient {
}
return authResponse.json();
}
async #getCommitment(commitmentKey) {
async #getCommitment(commitmentKey, blockHash = null) {
const params = blockHash ? [commitmentKey, blockHash] : [commitmentKey]

const commitmentResponse = await postHttpRequest({
url: this.substrateNodeURL,
headers: {
Expand All @@ -35,7 +37,7 @@ export class SxTClient {
id: 1,
jsonrpc: "2.0",
method: "state_getStorage",
params: [commitmentKey],
params,
},
});

Expand Down Expand Up @@ -66,11 +68,11 @@ export class SxTClient {
return proverResponse.json();
}

async queryAndVerify(queryString, table) {
async queryAndVerify(queryString, table, blockHash = null) {
const commitmentKey = "0x" + commitment_storage_key_dory(table);
const authResponse = await this.#getAccessToken();
const accessToken = authResponse.accessToken;
const commitmentResponse = await this.#getCommitment(commitmentKey);
const commitmentResponse = await this.#getCommitment(commitmentKey, blockHash);
const commitment = commitmentResponse.result.slice(2); // remove the 0x prefix

let commitments = [new TableRefAndCommitment(table, commitment)];
Expand Down

0 comments on commit e500875

Please sign in to comment.