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 }