/ console / program / src / state_path / mod.rs
mod.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  mod configuration;
 20  pub use configuration::*;
 21  
 22  mod header_leaf;
 23  pub use header_leaf::*;
 24  
 25  mod transaction_leaf;
 26  pub use transaction_leaf::*;
 27  
 28  pub mod transition_leaf;
 29  pub use transition_leaf::*;
 30  
 31  mod bytes;
 32  mod parse;
 33  mod serialize;
 34  mod verify;
 35  
 36  use alphavm_console_network::prelude::*;
 37  use alphavm_console_types::Field;
 38  
 39  /// The state path proves existence of the transition leaf to either a global or local state root.
 40  #[derive(Clone, PartialEq, Eq)]
 41  pub struct StatePath<N: Network> {
 42      /// The global state root (Public).
 43      global_state_root: N::StateRoot,
 44      /// The Merkle path for the block hash.
 45      block_path: BlockPath<N>,
 46      /// The block hash.
 47      block_hash: N::BlockHash,
 48      /// The previous block hash.
 49      previous_block_hash: N::BlockHash,
 50      /// The block header root.
 51      header_root: Field<N>,
 52      /// The Merkle path for the block header leaf.
 53      header_path: HeaderPath<N>,
 54      /// The block header leaf.
 55      header_leaf: HeaderLeaf<N>,
 56      /// The Merkle path for the transaction ID.
 57      transactions_path: TransactionsPath<N>,
 58      /// The transaction ID.
 59      transaction_id: N::TransactionID,
 60      /// The Merkle path for the transaction leaf.
 61      transaction_path: TransactionPath<N>,
 62      /// The transaction leaf.
 63      transaction_leaf: TransactionLeaf<N>,
 64      /// The transition root.
 65      transition_root: Field<N>,
 66      /// The transition commitment.
 67      tcm: Field<N>,
 68      /// The Merkle path for the transition leaf.
 69      transition_path: TransitionPath<N>,
 70      /// The transition leaf.
 71      transition_leaf: TransitionLeaf<N>,
 72  }
 73  
 74  impl<N: Network> StatePath<N> {
 75      /// Initializes a new instance of `StatePath`.
 76      pub fn new_local(
 77          global_state_root: N::StateRoot,
 78          local_state_root: N::TransactionID,
 79          transaction_path: TransactionPath<N>,
 80          transaction_leaf: TransactionLeaf<N>,
 81          transition_root: Field<N>,
 82          tcm: Field<N>,
 83          transition_path: TransitionPath<N>,
 84          transition_leaf: TransitionLeaf<N>,
 85      ) -> Result<Self> {
 86          // Compute an arbitrary transactions path.
 87          let local_state_root_bits = local_state_root.to_bits_le();
 88          let transactions_tree: TransactionsTree<N> = N::merkle_tree_bhp(std::slice::from_ref(&local_state_root_bits))?;
 89          let transactions_path = transactions_tree.prove(0, &local_state_root_bits)?;
 90          let transactions_root = transactions_tree.root();
 91  
 92          // Compute an arbitrary block header path.
 93          let header_leaf = HeaderLeaf::<N>::new(0, *transactions_root);
 94          let header_leaf_bits = header_leaf.to_bits_le();
 95          let header_tree: HeaderTree<N> = N::merkle_tree_bhp(std::slice::from_ref(&header_leaf_bits))?;
 96          let header_path = header_tree.prove(0, &header_leaf_bits)?;
 97          let header_root = *header_tree.root();
 98  
 99          // Compute an arbitrary block path.
100          let previous_block_hash: N::BlockHash = Field::<N>::zero().into();
101          let block_hash: N::BlockHash = previous_block_hash;
102          let block_hash_bits = block_hash.to_bits_le();
103          let block_tree: BlockTree<N> = N::merkle_tree_bhp(std::slice::from_ref(&block_hash_bits))?;
104          let block_path = block_tree.prove(0, &block_hash_bits)?;
105  
106          // Return the state path.
107          Ok(Self {
108              global_state_root,
109              block_path,
110              block_hash,
111              previous_block_hash,
112              header_root,
113              header_path,
114              header_leaf,
115              transactions_path,
116              transaction_id: local_state_root,
117              transaction_path,
118              transaction_leaf,
119              transition_root,
120              tcm,
121              transition_path,
122              transition_leaf,
123          })
124      }
125  
126      /// Initializes a new instance of `StatePath`.
127      #[allow(clippy::too_many_arguments)]
128      pub fn from(
129          global_state_root: N::StateRoot,
130          block_path: BlockPath<N>,
131          block_hash: N::BlockHash,
132          previous_block_hash: N::BlockHash,
133          header_root: Field<N>,
134          header_path: HeaderPath<N>,
135          header_leaf: HeaderLeaf<N>,
136          transactions_path: TransactionsPath<N>,
137          transaction_id: N::TransactionID,
138          transaction_path: TransactionPath<N>,
139          transaction_leaf: TransactionLeaf<N>,
140          transition_root: Field<N>,
141          tcm: Field<N>,
142          transition_path: TransitionPath<N>,
143          transition_leaf: TransitionLeaf<N>,
144      ) -> Self {
145          // Return the state path.
146          Self {
147              global_state_root,
148              block_path,
149              block_hash,
150              previous_block_hash,
151              header_root,
152              header_path,
153              header_leaf,
154              transactions_path,
155              transaction_id,
156              transaction_path,
157              transaction_leaf,
158              transition_root,
159              tcm,
160              transition_path,
161              transition_leaf,
162          }
163      }
164  
165      /// Returns the global state root.
166      pub const fn global_state_root(&self) -> N::StateRoot {
167          self.global_state_root
168      }
169  
170      /// Returns the block path.
171      pub const fn block_path(&self) -> &BlockPath<N> {
172          &self.block_path
173      }
174  
175      /// Returns the block hash.
176      pub const fn block_hash(&self) -> N::BlockHash {
177          self.block_hash
178      }
179  
180      /// Returns the previous block hash.
181      pub const fn previous_block_hash(&self) -> N::BlockHash {
182          self.previous_block_hash
183      }
184  
185      /// Returns the block header root.
186      pub const fn header_root(&self) -> &Field<N> {
187          &self.header_root
188      }
189  
190      /// Returns the header path.
191      pub const fn header_path(&self) -> &HeaderPath<N> {
192          &self.header_path
193      }
194  
195      /// Returns the header leaf.
196      pub const fn header_leaf(&self) -> &HeaderLeaf<N> {
197          &self.header_leaf
198      }
199  
200      /// Returns the transactions path.
201      pub const fn transactions_path(&self) -> &TransactionsPath<N> {
202          &self.transactions_path
203      }
204  
205      /// Returns the transaction ID.
206      pub const fn transaction_id(&self) -> &N::TransactionID {
207          &self.transaction_id
208      }
209  
210      /// Returns the Merkle path for the transaction leaf.
211      pub const fn transaction_path(&self) -> &TransactionPath<N> {
212          &self.transaction_path
213      }
214  
215      /// Returns the transaction leaf.
216      pub const fn transaction_leaf(&self) -> &TransactionLeaf<N> {
217          &self.transaction_leaf
218      }
219  
220      /// Returns the transition root.
221      pub const fn transition_root(&self) -> &Field<N> {
222          &self.transition_root
223      }
224  
225      /// Returns the transition commitment.
226      pub const fn tcm(&self) -> &Field<N> {
227          &self.tcm
228      }
229  
230      /// Returns the Merkle path for the transition leaf.
231      pub const fn transition_path(&self) -> &TransitionPath<N> {
232          &self.transition_path
233      }
234  
235      /// Returns the transition leaf.
236      pub const fn transition_leaf(&self) -> &TransitionLeaf<N> {
237          &self.transition_leaf
238      }
239  }
240  
241  #[cfg(any(test, feature = "test"))]
242  pub mod test_helpers {
243      use super::*;
244      use alphavm_console_network::prelude::TestRng;
245  
246      /// Randomly sample a state path to a global state root.
247      /// If a `commitment` is given, it is used. Otherwise, a `commitment` is randomly sampled.
248      pub fn sample_global_state_path<N: Network>(
249          commitment: Option<Field<N>>,
250          rng: &mut TestRng,
251      ) -> Result<StatePath<N>> {
252          // Prepare the commitment.
253          let commitment = match commitment {
254              Some(commitment) => commitment,
255              None => Field::rand(rng),
256          };
257  
258          // Prepare the tcm.
259          let tcm = Field::rand(rng);
260  
261          // Construct the transition path and transaction leaf.
262          let transition_leaf = TransitionLeaf::new_with_version(0, 3, commitment);
263          let transition_tree: TransitionTree<N> = N::merkle_tree_bhp(&[transition_leaf.to_bits_le()])?;
264          let transition_root = *transition_tree.root();
265          let transition_id = N::hash_bhp512(&(transition_root, tcm).to_bits_le())?;
266          let transition_path = transition_tree.prove(0, &transition_leaf.to_bits_le())?;
267  
268          // Construct the transaction path and transaction leaf.
269          let transaction_leaf = TransactionLeaf::new_execution(0, transition_id);
270          let transaction_tree: TransactionTree<N> = N::merkle_tree_bhp(&[transaction_leaf.to_bits_le()])?;
271          let transaction_id = *transaction_tree.root();
272          let transaction_path = transaction_tree.prove(0, &transaction_leaf.to_bits_le())?;
273  
274          // Construct the transactions path.
275          let transactions_tree: TransactionsTree<N> = N::merkle_tree_bhp(&[transaction_id.to_bits_le()])?;
276          let transactions_root = transactions_tree.root();
277          let transactions_path = transactions_tree.prove(0, &transaction_id.to_bits_le())?;
278  
279          // Construct the block header path.
280          let header_leaf = HeaderLeaf::<N>::new(1, *transactions_root);
281          let header_tree: HeaderTree<N> =
282              N::merkle_tree_bhp(&[Field::<N>::zero().to_bits_le(), header_leaf.to_bits_le()])?;
283          let header_root = header_tree.root();
284          let header_path = header_tree.prove(1, &header_leaf.to_bits_le())?;
285  
286          let previous_block_hash: N::BlockHash = Field::<N>::rand(rng).into();
287          let preimage = (*previous_block_hash).to_bits_le().into_iter().chain(header_root.to_bits_le());
288          let block_hash = N::hash_bhp1024(&preimage.collect::<Vec<_>>())?;
289  
290          // Construct the global state root and block path.
291          let block_tree: BlockTree<N> = N::merkle_tree_bhp(&[block_hash.to_bits_le()])?;
292          let global_state_root = *block_tree.root();
293          let block_path = block_tree.prove(0, &block_hash.to_bits_le())?;
294  
295          Ok(StatePath::<N>::from(
296              global_state_root.into(),
297              block_path,
298              block_hash.into(),
299              previous_block_hash,
300              *header_root,
301              header_path,
302              header_leaf,
303              transactions_path,
304              transaction_id.into(),
305              transaction_path,
306              transaction_leaf,
307              transition_root,
308              tcm,
309              transition_path,
310              transition_leaf,
311          ))
312      }
313  
314      /// Randomly sample a state path to a local state root.
315      /// If a `commitment` is given, it is used. Otherwise, a `commitment` is randomly sampled.
316      pub fn sample_local_state_path<N: Network>(
317          commitment: Option<Field<N>>,
318          rng: &mut TestRng,
319      ) -> Result<StatePath<N>> {
320          // Prepare the commitment.
321          let commitment = match commitment {
322              Some(commitment) => commitment,
323              None => Field::rand(rng),
324          };
325  
326          // Prepare the tcm.
327          let tcm = Field::rand(rng);
328  
329          // Construct the transition path and transaction leaf.
330          let transition_leaf = TransitionLeaf::new_with_version(0, 3, commitment);
331          let transition_tree: TransitionTree<N> = N::merkle_tree_bhp(&[transition_leaf.to_bits_le()])?;
332          let transition_root = *transition_tree.root();
333          let transition_id = N::hash_bhp512(&(transition_root, tcm).to_bits_le())?;
334          let transition_path = transition_tree.prove(0, &transition_leaf.to_bits_le())?;
335  
336          // Construct the transaction path and transaction leaf.
337          let transaction_leaf = TransactionLeaf::new_execution(0, transition_id);
338          let transaction_tree: TransactionTree<N> = N::merkle_tree_bhp(&[transaction_leaf.to_bits_le()])?;
339          let transaction_id = *transaction_tree.root();
340          let transaction_path = transaction_tree.prove(0, &transaction_leaf.to_bits_le())?;
341  
342          // Construct the transactions path.
343          let transactions_tree: TransactionsTree<N> = N::merkle_tree_bhp(&[transaction_id.to_bits_le()])?;
344          let transactions_root = transactions_tree.root();
345          let transactions_path = transactions_tree.prove(0, &transaction_id.to_bits_le())?;
346  
347          // Prepare random header leaves.
348          let random_header_index = rng.gen_range(0..7);
349          let mut random_header_leaves = vec![Field::<N>::zero().to_bits_le(); (random_header_index + 1) as usize];
350          let header_leaf = HeaderLeaf::<N>::new(random_header_index, *transactions_root);
351          random_header_leaves[random_header_index as usize] = header_leaf.to_bits_le();
352  
353          // Construct the block header path.
354          let header_tree: HeaderTree<N> = N::merkle_tree_bhp(&random_header_leaves)?;
355          let header_root = header_tree.root();
356          let header_path = header_tree.prove(random_header_index as usize, &header_leaf.to_bits_le())?;
357  
358          let previous_block_hash: N::BlockHash = Field::<N>::rand(rng).into();
359          let block_hash: N::BlockHash = Field::<N>::rand(rng).into();
360  
361          // Construct the global state root and block path.
362          let block_tree: BlockTree<N> = N::merkle_tree_bhp(&[block_hash.to_bits_le()])?;
363          let global_state_root = *block_tree.root();
364          let block_path = block_tree.prove(0, &block_hash.to_bits_le())?;
365  
366          Ok(StatePath::<N>::from(
367              global_state_root.into(),
368              block_path,
369              block_hash,
370              previous_block_hash,
371              *header_root,
372              header_path,
373              header_leaf,
374              transactions_path,
375              transaction_id.into(),
376              transaction_path,
377              transaction_leaf,
378              transition_root,
379              tcm,
380              transition_path,
381              transition_leaf,
382          ))
383      }
384  }