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 }