/ ledger / query / src / query / static_.rs
static_.rs
  1  // Copyright (c) 2025-2026 ACDC Network
  2  // This file is part of the alphavm library.
  3  //
  4  // Alpha Chain | Delta Chain Protocol
  5  // International Monetary Graphite.
  6  //
  7  // Derived from Aleo (https://aleo.org) and ProvableHQ (https://provable.com).
  8  // They built world-class ZK infrastructure. We installed the EASY button.
  9  // Their cryptography: elegant. Our modifications: bureaucracy-compatible.
 10  // Original brilliance: theirs. Robert's Rules: ours. Bugs: definitely ours.
 11  //
 12  // Original Aleo/ProvableHQ code subject to Apache 2.0 https://www.apache.org/licenses/LICENSE-2.0
 13  // All modifications and new work: CC0 1.0 Universal Public Domain Dedication.
 14  // No rights reserved. No permission required. No warranty. No refunds.
 15  //
 16  // https://creativecommons.org/publicdomain/zero/1.0/
 17  // SPDX-License-Identifier: CC0-1.0
 18  
 19  use crate::QueryTrait;
 20  
 21  use alphavm_console::{network::prelude::*, program::StatePath, types::Field};
 22  
 23  use anyhow::{ensure, Context, Result};
 24  use serde::Deserialize;
 25  use std::{collections::HashMap, str::FromStr};
 26  
 27  #[derive(Clone)]
 28  pub struct StaticQuery<N: Network> {
 29      block_height: u32,
 30      state_root: N::StateRoot,
 31      state_paths: HashMap<Field<N>, StatePath<N>>,
 32  }
 33  
 34  impl<N: Network> StaticQuery<N> {
 35      pub fn new(block_height: u32, state_root: N::StateRoot, state_paths: HashMap<Field<N>, StatePath<N>>) -> Self {
 36          Self { block_height, state_root, state_paths }
 37      }
 38  }
 39  
 40  #[derive(Deserialize)]
 41  struct StaticQueryInput {
 42      state_root: String,
 43      height: u32,
 44  }
 45  
 46  impl<N: Network> FromStr for StaticQuery<N> {
 47      type Err = anyhow::Error;
 48  
 49      fn from_str(s: &str) -> Result<Self> {
 50          ensure!(s.trim().starts_with('{'), "Not a static query");
 51  
 52          let input: StaticQueryInput = serde_json::from_str(s).with_context(|| "Invalid JSON format in static query")?;
 53          let state_root = N::StateRoot::from_str(&input.state_root).map_err(|_| anyhow!("Invalid state root format"))?;
 54  
 55          Ok(Self { state_root, block_height: input.height, state_paths: HashMap::new() })
 56      }
 57  }
 58  
 59  #[cfg_attr(feature = "async", async_trait::async_trait(?Send))]
 60  impl<N: Network> QueryTrait<N> for StaticQuery<N> {
 61      /// Returns the current state root.
 62      fn current_state_root(&self) -> Result<N::StateRoot> {
 63          Ok(self.state_root)
 64      }
 65  
 66      /// Returns the current state root (async version).
 67      #[cfg(feature = "async")]
 68      async fn current_state_root_async(&self) -> Result<N::StateRoot> {
 69          // There is no I/O in StaticQuery, so the sync version is identical.
 70          self.current_state_root()
 71      }
 72  
 73      /// Returns a state path for the given `commitment`.
 74      fn get_state_path_for_commitment(&self, commitment: &Field<N>) -> Result<StatePath<N>> {
 75          match self.state_paths.get(commitment) {
 76              Some(state_path) => Ok(state_path.clone()),
 77              None => bail!("Could not find state path for commitment '{commitment}'"),
 78          }
 79      }
 80  
 81      /// Returns a state path for the given `commitment` (async version).
 82      #[cfg(feature = "async")]
 83      async fn get_state_path_for_commitment_async(&self, commitment: &Field<N>) -> Result<StatePath<N>> {
 84          // There is no I/O in StaticQuery, so the sync version is identical.
 85          self.get_state_path_for_commitment(commitment)
 86      }
 87  
 88      /// Returns a list of state paths for the given list of `commitment`s.
 89      fn get_state_paths_for_commitments(&self, commitments: &[Field<N>]) -> Result<Vec<StatePath<N>>> {
 90          commitments
 91              .iter()
 92              .map(|commitment| self.get_state_path_for_commitment(commitment))
 93              .collect::<Result<Vec<StatePath<N>>>>()
 94      }
 95  
 96      /// Returns a list of state paths for the given list of `commitment`s (async version).
 97      #[cfg(feature = "async")]
 98      async fn get_state_paths_for_commitments_async(&self, commitments: &[Field<N>]) -> Result<Vec<StatePath<N>>> {
 99          // There is no I/O in StaticQuery, so the sync version is identical.
100          self.get_state_paths_for_commitments(commitments)
101      }
102  
103      /// Returns the current block height.
104      fn current_block_height(&self) -> Result<u32> {
105          Ok(self.block_height)
106      }
107  
108      /// Returns the current block height (async version).
109      #[cfg(feature = "async")]
110      async fn current_block_height_async(&self) -> Result<u32> {
111          // There is no I/O in StaticQuery, so the sync version is identical.
112          self.current_block_height()
113      }
114  }
115  
116  #[cfg(test)]
117  mod tests {
118      use super::*;
119      use alphavm_console::network::TestnetV0;
120  
121      #[test]
122      fn test_static_query_parse() {
123          let json = r#"{"state_root": "sr1dz06ur5spdgzkguh4pr42mvft6u3nwsg5drh9rdja9v8jpcz3czsls9geg", "height": 14}"#
124              .to_string();
125          let query: Result<StaticQuery<TestnetV0>> = json.parse();
126          assert!(query.is_ok());
127      }
128  
129      #[test]
130      fn test_static_query_parse_invalid() {
131          let json = r#"{"invalid_key": "sr1dz06ur5spdgzkguh4pr42mvft6u3nwsg5drh9rdja9v8jpcz3czsls9geg", "height": 14}"#
132              .to_string();
133          let query: Result<StaticQuery<TestnetV0>> = json.parse();
134          assert!(query.is_err());
135      }
136  }