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