lib.rs
1 // Copyright (c) 2019-2025 Alpha-Delta Network Inc. 2 // This file is part of the alphavm 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 extern crate alphavm_circuit as circuit; 17 extern crate alphavm_console as console; 18 19 use alphavm_algorithms::snark::varuna::VarunaVersion; 20 use alphavm_ledger_block::{ 21 Block, 22 ConfirmedTransaction, 23 Deployment, 24 Execution, 25 Fee, 26 Header, 27 Input, 28 Output, 29 Ratifications, 30 Rejected, 31 Transaction, 32 Transactions, 33 Transition, 34 }; 35 use alphavm_ledger_query::Query; 36 use alphavm_ledger_store::{BlockStore, helpers::memory::BlockMemory}; 37 use alphavm_synthesizer_process::Process; 38 use alphavm_synthesizer_program::Program; 39 use alphavm_utilities::PrettyUnwrap; 40 use console::{ 41 account::{Address, PrivateKey}, 42 prelude::*, 43 program::{Ciphertext, Literal, Plaintext, ProgramOwner, Record, Value}, 44 types::Field, 45 }; 46 47 use alphastd::StorageMode; 48 use anyhow::Context; 49 use std::sync::OnceLock; 50 51 type CurrentNetwork = console::network::MainnetV0; 52 type CurrentAlpha = circuit::network::AlphaV0; 53 54 /****************************************** Transition ********************************************/ 55 56 /// Samples a random transition. 57 pub fn sample_transition(rng: &mut TestRng) -> Transition<CurrentNetwork> { 58 crate::sample_execution(rng, 0).into_transitions().next().unwrap() 59 } 60 61 /// Sample the transition inputs. 62 pub fn sample_inputs() -> Vec<(<CurrentNetwork as Network>::TransitionID, Input<CurrentNetwork>)> { 63 let rng = &mut TestRng::default(); 64 65 // Sample a transition. 66 let transaction = crate::sample_execution_transaction_with_fee(true, rng, 0); 67 let transition = transaction.transitions().next().unwrap(); 68 69 // Retrieve the transition ID and input. 70 let transition_id = *transition.id(); 71 let input = transition.inputs().iter().next().unwrap().clone(); 72 73 // Sample a random plaintext. 74 let plaintext = Plaintext::Literal(Literal::Field(Uniform::rand(rng)), Default::default()); 75 let plaintext_hash = CurrentNetwork::hash_bhp1024(&plaintext.to_bits_le()).unwrap(); 76 // Sample a random ciphertext. 77 let fields: Vec<_> = (0..10).map(|_| Uniform::rand(rng)).collect(); 78 let ciphertext = Ciphertext::from_fields(&fields).unwrap(); 79 let ciphertext_hash = CurrentNetwork::hash_bhp1024(&ciphertext.to_bits_le()).unwrap(); 80 81 vec![ 82 (transition_id, input), 83 (Uniform::rand(rng), Input::Constant(Uniform::rand(rng), None)), 84 (Uniform::rand(rng), Input::Constant(plaintext_hash, Some(plaintext.clone()))), 85 (Uniform::rand(rng), Input::Public(Uniform::rand(rng), None)), 86 (Uniform::rand(rng), Input::Public(plaintext_hash, Some(plaintext))), 87 (Uniform::rand(rng), Input::Private(Uniform::rand(rng), None)), 88 (Uniform::rand(rng), Input::Private(ciphertext_hash, Some(ciphertext))), 89 (Uniform::rand(rng), Input::Record(Uniform::rand(rng), Uniform::rand(rng))), 90 (Uniform::rand(rng), Input::ExternalRecord(Uniform::rand(rng))), 91 ] 92 } 93 94 /// Sample the transition outputs. 95 pub fn sample_outputs() -> Vec<(<CurrentNetwork as Network>::TransitionID, Output<CurrentNetwork>)> { 96 let rng = &mut TestRng::default(); 97 98 // Sample a transition. 99 let transaction = crate::sample_execution_transaction_with_fee(true, rng, 0); 100 let transition = transaction.transitions().next().unwrap(); 101 102 // Retrieve the transition ID and input. 103 let transition_id = *transition.id(); 104 let input = transition.outputs().iter().next().unwrap().clone(); 105 106 // Sample a random plaintext. 107 let plaintext = Plaintext::Literal(Literal::Field(Uniform::rand(rng)), Default::default()); 108 let plaintext_hash = CurrentNetwork::hash_bhp1024(&plaintext.to_bits_le()).unwrap(); 109 // Sample a random ciphertext. 110 let fields: Vec<_> = (0..10).map(|_| Uniform::rand(rng)).collect(); 111 let ciphertext = Ciphertext::from_fields(&fields).unwrap(); 112 let ciphertext_hash = CurrentNetwork::hash_bhp1024(&ciphertext.to_bits_le()).unwrap(); 113 // Sample a random record. 114 let randomizer = Uniform::rand(rng); 115 let nonce = CurrentNetwork::g_scalar_multiply(&randomizer); 116 let record = Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::from_str( 117 &format!("{{ owner: ax150w2lvhdzychwvzu54ys5zas7tm5s0ycdyw563pms83g9u0vucgqe5fs5w.private, token_amount: 100u64.private, _nonce: {nonce}.public }}"), 118 ).unwrap(); 119 let record_ciphertext = record.encrypt(randomizer).unwrap(); 120 let record_checksum = CurrentNetwork::hash_bhp1024(&record_ciphertext.to_bits_le()).unwrap(); 121 // Sample a sender ciphertext. 122 let sender_ciphertext = match record_ciphertext.version().is_zero() { 123 true => None, 124 false => Some(Uniform::rand(rng)), 125 }; 126 127 vec![ 128 (transition_id, input), 129 (Uniform::rand(rng), Output::Constant(Uniform::rand(rng), None)), 130 (Uniform::rand(rng), Output::Constant(plaintext_hash, Some(plaintext.clone()))), 131 (Uniform::rand(rng), Output::Public(Uniform::rand(rng), None)), 132 (Uniform::rand(rng), Output::Public(plaintext_hash, Some(plaintext))), 133 (Uniform::rand(rng), Output::Private(Uniform::rand(rng), None)), 134 (Uniform::rand(rng), Output::Private(ciphertext_hash, Some(ciphertext))), 135 (Uniform::rand(rng), Output::Record(Uniform::rand(rng), Uniform::rand(rng), None, sender_ciphertext)), 136 ( 137 Uniform::rand(rng), 138 Output::Record(Uniform::rand(rng), record_checksum, Some(record_ciphertext), sender_ciphertext), 139 ), 140 (Uniform::rand(rng), Output::ExternalRecord(Uniform::rand(rng))), 141 ] 142 } 143 144 /******************************************* Deployment *******************************************/ 145 146 pub fn sample_deployment_v1(edition: u16, rng: &mut TestRng) -> Deployment<CurrentNetwork> { 147 static INSTANCE: OnceLock<Deployment<CurrentNetwork>> = OnceLock::new(); 148 let deployment = INSTANCE 149 .get_or_init(|| { 150 // Initialize a new program. 151 let (string, program) = Program::<CurrentNetwork>::parse( 152 r" 153 program testing_one.alpha; 154 155 mapping store: 156 key as u32.public; 157 value as u32.public; 158 159 function compute: 160 input r0 as u32.private; 161 add r0 r0 into r1; 162 output r1 as u32.public;", 163 ) 164 .unwrap(); 165 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 166 // Construct the process. 167 let process = Process::load().unwrap(); 168 // Compute the deployment. 169 let mut deployment = process.deploy::<CurrentAlpha, _>(&program, rng).unwrap(); 170 // Unset the checksum. 171 deployment.set_program_checksum_raw(None); 172 // Unset the owner. 173 deployment.set_program_owner_raw(None); 174 // Return the deployment. 175 // Note: This is a testing-only hack to adhere to Rust's dependency cycle rules. 176 Deployment::from_str(&deployment.to_string()).unwrap() 177 }) 178 .clone(); 179 // Create a new deployment with the desired edition. 180 Deployment::<CurrentNetwork>::new( 181 edition % 2, 182 deployment.program().clone(), 183 deployment.verifying_keys().clone(), 184 deployment.program_checksum(), 185 deployment.program_owner(), 186 ) 187 .unwrap() 188 } 189 190 pub fn sample_deployment_v2(edition: u16, rng: &mut TestRng) -> Deployment<CurrentNetwork> { 191 static INSTANCE: OnceLock<Deployment<CurrentNetwork>> = OnceLock::new(); 192 let deployment = INSTANCE 193 .get_or_init(|| { 194 // Initialize a new program. 195 let (string, program) = Program::<CurrentNetwork>::parse( 196 r" 197 program testing_two.alpha; 198 199 mapping store: 200 key as u32.public; 201 value as u32.public; 202 203 function compute: 204 input r0 as u32.private; 205 add r0 r0 into r1; 206 output r1 as u32.public;", 207 ) 208 .unwrap(); 209 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 210 // Construct the process. 211 let process = Process::load().unwrap(); 212 // Compute the deployment. 213 let mut deployment = process.deploy::<CurrentAlpha, _>(&program, rng).unwrap(); 214 // Set the program checksum. 215 deployment.set_program_checksum_raw(Some(deployment.program().to_checksum())); 216 // Set the program owner. 217 deployment.set_program_owner_raw(Some(Address::rand(rng))); 218 // Return the deployment. 219 // Note: This is a testing-only hack to adhere to Rust's dependency cycle rules. 220 Deployment::from_str(&deployment.to_string()).unwrap() 221 }) 222 .clone(); 223 // Create a new deployment with the desired edition. 224 Deployment::<CurrentNetwork>::new( 225 edition, 226 deployment.program().clone(), 227 deployment.verifying_keys().clone(), 228 deployment.program_checksum(), 229 deployment.program_owner(), 230 ) 231 .unwrap() 232 } 233 234 /// Samples a rejected deployment. 235 pub fn sample_rejected_deployment( 236 version: u8, 237 edition: u16, 238 is_fee_private: bool, 239 rng: &mut TestRng, 240 ) -> Rejected<CurrentNetwork> { 241 // Sample a deploy transaction. 242 let deployment = match crate::sample_deployment_transaction(version, edition, is_fee_private, rng) { 243 Transaction::Deploy(_, _, _, deployment, _) => (*deployment).clone(), 244 _ => unreachable!(), 245 }; 246 247 // Sample a new program owner. 248 let private_key = PrivateKey::new(rng).unwrap(); 249 let deployment_id = deployment.to_deployment_id().unwrap(); 250 let program_owner = ProgramOwner::new(&private_key, deployment_id, rng).unwrap(); 251 252 // Return the rejected deployment. 253 Rejected::new_deployment(program_owner, deployment) 254 } 255 256 /******************************************* Execution ********************************************/ 257 258 /// Samples a random execution. 259 pub fn sample_execution(rng: &mut TestRng, index: usize) -> Execution<CurrentNetwork> { 260 // Sample the genesis block. 261 let block = crate::sample_genesis_block(rng); 262 // Retrieve a transaction. 263 let transaction = block.transactions().iter().nth(index).unwrap().deref().clone(); 264 // Retrieve the execution. 265 if let Transaction::Execute(_, _, execution, _) = transaction { 266 *execution 267 } else { 268 panic!("Index {index} exceeded the number of executions in the genesis block") 269 } 270 } 271 272 /// Samples a rejected execution. 273 pub fn sample_rejected_execution(is_fee_private: bool, rng: &mut TestRng) -> Rejected<CurrentNetwork> { 274 // Sample an execute transaction. 275 let execution = match crate::sample_execution_transaction_with_fee(is_fee_private, rng, 0) { 276 Transaction::Execute(_, _, execution, _) => execution, 277 _ => unreachable!(), 278 }; 279 280 // Return the rejected execution. 281 Rejected::new_execution(*execution) 282 } 283 284 /********************************************** Fee ***********************************************/ 285 286 /// Samples a random hardcoded private fee. 287 pub fn sample_fee_private_hardcoded(rng: &mut TestRng) -> Fee<CurrentNetwork> { 288 static INSTANCE: OnceLock<Fee<CurrentNetwork>> = OnceLock::new(); 289 INSTANCE 290 .get_or_init(|| { 291 // Sample a deployment or execution ID. 292 let deployment_or_execution_id = Field::rand(rng); 293 // Sample a fee. 294 sample_fee_private(deployment_or_execution_id, rng) 295 }) 296 .clone() 297 } 298 299 /// Samples a random private fee. 300 pub fn sample_fee_private(deployment_or_execution_id: Field<CurrentNetwork>, rng: &mut TestRng) -> Fee<CurrentNetwork> { 301 // Sample the genesis block, transaction, and private key. 302 let (block, transactions, private_key) = crate::sample_genesis_block_and_components(rng); 303 // Retrieve a credits record. 304 let credits = transactions.iter().next().unwrap().records().next().unwrap().1.clone(); 305 // Decrypt the record. 306 let credits = credits.decrypt(&private_key.try_into().unwrap()).unwrap(); 307 // Sample a base fee in microcredits. 308 let base_fee_in_microcredits = 10_000_000; 309 // Sample a priority fee in microcredits. 310 let priority_fee_in_microcredits = 1_000; 311 312 // Initialize the process. 313 let process = Process::load().unwrap(); 314 // Authorize the fee. 315 let authorization = process 316 .authorize_fee_private::<CurrentAlpha, _>( 317 &private_key, 318 credits, 319 base_fee_in_microcredits, 320 priority_fee_in_microcredits, 321 deployment_or_execution_id, 322 rng, 323 ) 324 .unwrap(); 325 // Construct the fee trace. 326 let (_, mut trace) = process.execute::<CurrentAlpha, _>(authorization, rng).unwrap(); 327 328 // Initialize a new block store. 329 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 330 // Insert the block into the block store. 331 // Note: This is a testing-only hack to adhere to Rust's dependency cycle rules. 332 block_store.insert(&FromStr::from_str(&block.to_string()).unwrap()).unwrap(); 333 334 // Prepare the assignments. 335 trace.prepare(&Query::from(block_store)).unwrap(); 336 // Compute the proof and construct the fee. 337 let fee = trace.prove_fee::<CurrentAlpha, _>(VarunaVersion::V1, rng).unwrap(); 338 339 // Convert the fee. 340 // Note: This is a testing-only hack to adhere to Rust's dependency cycle rules. 341 Fee::from_str(&fee.to_string()).unwrap() 342 } 343 344 /// Samples a random hardcoded public fee. 345 pub fn sample_fee_public_hardcoded(rng: &mut TestRng) -> Fee<CurrentNetwork> { 346 static INSTANCE: OnceLock<Fee<CurrentNetwork>> = OnceLock::new(); 347 INSTANCE 348 .get_or_init(|| { 349 // Sample a deployment or execution ID. 350 let deployment_or_execution_id = Field::rand(rng); 351 // Sample a fee. 352 sample_fee_public(deployment_or_execution_id, rng) 353 }) 354 .clone() 355 } 356 357 /// Samples a random public fee. 358 pub fn sample_fee_public(deployment_or_execution_id: Field<CurrentNetwork>, rng: &mut TestRng) -> Fee<CurrentNetwork> { 359 // Sample the genesis block, transaction, and private key. 360 let (block, _, private_key) = crate::sample_genesis_block_and_components(rng); 361 // Sample a base fee in microcredits. 362 let base_fee_in_microcredits = 10_000_000; 363 // Sample a priority fee in microcredits. 364 let priority_fee_in_microcredits = 1_000; 365 366 // Initialize the process. 367 let process = Process::load().unwrap(); 368 // Authorize the fee. 369 let authorization = process 370 .authorize_fee_public::<CurrentAlpha, _>( 371 &private_key, 372 base_fee_in_microcredits, 373 priority_fee_in_microcredits, 374 deployment_or_execution_id, 375 rng, 376 ) 377 .unwrap(); 378 // Construct the fee trace. 379 let (_, mut trace) = process.execute::<CurrentAlpha, _>(authorization, rng).unwrap(); 380 381 // Initialize a new block store. 382 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 383 // Insert the block into the block store. 384 // Note: This is a testing-only hack to adhere to Rust's dependency cycle rules. 385 block_store.insert(&FromStr::from_str(&block.to_string()).unwrap()).unwrap(); 386 387 // Prepare the assignments. 388 trace.prepare(&Query::from(block_store)).unwrap(); 389 // Compute the proof and construct the fee. 390 let fee = trace.prove_fee::<CurrentAlpha, _>(VarunaVersion::V1, rng).unwrap(); 391 392 // Convert the fee. 393 // Note: This is a testing-only hack to adhere to Rust's dependency cycle rules. 394 Fee::from_str(&fee.to_string()).unwrap() 395 } 396 397 /******************************************** Program *********************************************/ 398 399 /// Deploy a program that produces large transactions under the maximum transaction size. 400 pub fn small_transaction_program() -> Program<CurrentNetwork> { 401 Program::from_str( 402 r" 403 program testing_small.alpha; 404 function small_transaction: 405 cast 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field into r0 as [field; 32u32]; 406 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [[field; 32u32]; 32u32]; 407 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r2 as [[field; 32u32]; 32u32]; 408 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r3 as [[field; 32u32]; 32u32]; 409 output r1 as [[field; 32u32]; 32u32].public; 410 output r2 as [[field; 32u32]; 32u32].public; 411 output r3 as [[field; 32u32]; 32u32].public;").unwrap() 412 } 413 414 /// Deploy a program that produces large transactions above the maximum transaction size. 415 pub fn large_transaction_program() -> Program<CurrentNetwork> { 416 Program::from_str( 417 r" 418 program testing_large.alpha; 419 function large_transaction: 420 cast 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field 0field into r0 as [field; 32u32]; 421 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [[field; 32u32]; 27u32]; 422 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r2 as [[field; 32u32]; 27u32]; 423 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r3 as [[field; 32u32]; 27u32]; 424 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r4 as [[field; 32u32]; 27u32]; 425 output r1 as [[field; 32u32]; 27u32].public; 426 output r2 as [[field; 32u32]; 27u32].public; 427 output r3 as [[field; 32u32]; 27u32].public; 428 output r4 as [[field; 32u32]; 27u32].public;").unwrap() 429 } 430 431 /****************************************** Transaction *******************************************/ 432 433 /// Samples a random deployment transaction with a private or public fee. 434 pub fn sample_deployment_transaction( 435 version: u8, 436 edition: u16, 437 is_fee_private: bool, 438 rng: &mut TestRng, 439 ) -> Transaction<CurrentNetwork> { 440 // Sample a private key. 441 let private_key = PrivateKey::new(rng).unwrap(); 442 // Sample a deployment. 443 let deployment = match version { 444 1 => sample_deployment_v1(edition, rng), 445 2 => { 446 let mut deployment = sample_deployment_v2(edition, rng); 447 // Set the program checksum. 448 deployment.set_program_checksum_raw(Some(deployment.program().to_checksum())); 449 // Set the program owner to the address of the private key. 450 deployment.set_program_owner_raw(Some(Address::try_from(&private_key).unwrap())); 451 // Return the deployment. 452 deployment 453 } 454 _ => panic!("Invalid deployment version: {version}"), 455 }; 456 457 // Compute the deployment ID. 458 let deployment_id = deployment.to_deployment_id().unwrap(); 459 // Construct a program owner. 460 let owner = ProgramOwner::new(&private_key, deployment_id, rng).unwrap(); 461 462 // Sample the fee. 463 let fee = match is_fee_private { 464 true => crate::sample_fee_private(deployment_id, rng), 465 false => crate::sample_fee_public(deployment_id, rng), 466 }; 467 468 // Construct a deployment transaction. 469 Transaction::from_deployment(owner, deployment, fee).unwrap() 470 } 471 472 /// Samples a random execution transaction with a private or public fee. 473 pub fn sample_execution_transaction_with_fee( 474 is_fee_private: bool, 475 rng: &mut TestRng, 476 index: usize, 477 ) -> Transaction<CurrentNetwork> { 478 // Sample an execution. 479 let execution = crate::sample_execution(rng, index); 480 // Compute the execution ID. 481 let execution_id = execution.to_execution_id().unwrap(); 482 483 // Sample the fee. 484 let fee = match is_fee_private { 485 true => crate::sample_fee_private(execution_id, rng), 486 false => crate::sample_fee_public(execution_id, rng), 487 }; 488 489 // Construct an execution transaction. 490 Transaction::from_execution(execution, Some(fee)).unwrap() 491 } 492 493 /// Samples a large transaction. 494 pub fn sample_large_execution_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> { 495 static INSTANCE: std::sync::OnceLock<Execution<CurrentNetwork>> = std::sync::OnceLock::new(); 496 497 let execution = INSTANCE 498 .get_or_init(|| { 499 // Initialize a program that produces large transactions. 500 let program = large_transaction_program(); 501 502 // Construct the process. 503 let mut process = alphavm_synthesizer_process::Process::load().unwrap(); 504 // Add the program. 505 process.add_program(&program).unwrap(); 506 507 // Initialize a private key. 508 let private_key = PrivateKey::new(rng).unwrap(); 509 510 // Authorize the function. 511 let authorization = process 512 .authorize::<CurrentAlpha, _>( 513 &private_key, 514 "testing_large.alpha", 515 "large_transaction", 516 Vec::<Value<CurrentNetwork>>::new().iter(), 517 rng, 518 ) 519 .unwrap(); 520 // Execute the function. 521 let (_, mut trace) = process.execute::<CurrentAlpha, _>(authorization, rng).unwrap(); 522 523 // Initialize a new block store. 524 let block_store = alphavm_ledger_store::BlockStore::< 525 CurrentNetwork, 526 alphavm_ledger_store::helpers::memory::BlockMemory<_>, 527 >::open(StorageMode::new_test(None)) 528 .unwrap(); 529 530 // Prepare the assignments. 531 trace.prepare(&alphavm_ledger_query::Query::from(block_store)).unwrap(); 532 // Compute the proof and construct the execution. 533 let execution = trace.prove_execution::<CurrentAlpha, _>("testing.alpha", VarunaVersion::V1, rng).unwrap(); 534 // Reconstruct the execution from bytes. 535 // This is a hack to get around Rust dependency resolution. 536 Execution::from_bytes_le(&execution.to_bytes_le().unwrap()).unwrap() 537 }) 538 .clone(); 539 540 // Compute the execution ID. 541 let execution_id = execution.to_execution_id().unwrap(); 542 543 // Sample the fee. 544 let fee = crate::sample_fee_public(execution_id, rng); 545 546 // Construct an execution transaction. 547 Transaction::from_execution(execution, Some(fee)).unwrap() 548 } 549 550 /// Samples a random private fee transaction. 551 pub fn sample_fee_private_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> { 552 // Sample a private fee. 553 let fee = crate::sample_fee_private_hardcoded(rng); 554 // Construct a fee transaction. 555 Transaction::from_fee(fee).unwrap() 556 } 557 558 /// Samples a random public fee transaction. 559 pub fn sample_fee_public_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> { 560 // Sample a public fee. 561 let fee = crate::sample_fee_public_hardcoded(rng); 562 // Construct a fee transaction. 563 Transaction::from_fee(fee).unwrap() 564 } 565 566 /****************************************** Transactions ******************************************/ 567 568 /// Samples a block transactions. 569 pub fn sample_block_transactions(rng: &mut TestRng) -> Transactions<CurrentNetwork> { 570 crate::sample_genesis_block(rng).transactions().clone() 571 } 572 573 /********************************************* Block **********************************************/ 574 575 /// Samples a random genesis block. 576 pub fn sample_genesis_block(rng: &mut TestRng) -> Block<CurrentNetwork> { 577 // Sample the genesis block and components. 578 let (block, _, _) = crate::sample_genesis_block_and_components(rng); 579 // Return the block. 580 block 581 } 582 583 /// Samples a random genesis block and the transactions from the genesis block. 584 pub fn sample_genesis_block_and_transactions( 585 rng: &mut TestRng, 586 ) -> (Block<CurrentNetwork>, Transactions<CurrentNetwork>) { 587 // Sample the genesis block and components. 588 let (block, transactions, _) = crate::sample_genesis_block_and_components(rng); 589 // Return the block and transactions. 590 (block, transactions) 591 } 592 593 /// Samples a random genesis block, the transactions from the genesis block, and the genesis private key. 594 /// If this function was called before, this returns a cached version. 595 pub fn sample_genesis_block_and_components( 596 rng: &mut TestRng, 597 ) -> (Block<CurrentNetwork>, Transactions<CurrentNetwork>, PrivateKey<CurrentNetwork>) { 598 static INSTANCE: OnceLock<(Block<CurrentNetwork>, Transactions<CurrentNetwork>, PrivateKey<CurrentNetwork>)> = 599 OnceLock::new(); 600 INSTANCE.get_or_init(|| crate::sample_genesis_block_and_components_uncached(rng)).clone() 601 } 602 603 pub fn sample_genesis_private_key(rng: &mut TestRng) -> PrivateKey<CurrentNetwork> { 604 static INSTANCE: OnceLock<PrivateKey<CurrentNetwork>> = OnceLock::new(); 605 *INSTANCE.get_or_init(|| { 606 // Initialize a new caller. 607 PrivateKey::<CurrentNetwork>::new(rng).unwrap() 608 }) 609 } 610 611 /// Samples a random genesis block, the transactions from the genesis block, and the genesis private key. 612 pub fn sample_genesis_block_and_components_uncached( 613 rng: &mut TestRng, 614 ) -> (Block<CurrentNetwork>, Transactions<CurrentNetwork>, PrivateKey<CurrentNetwork>) { 615 // Sample the genesis private key. 616 let private_key = sample_genesis_private_key(rng); 617 let address = Address::<CurrentNetwork>::try_from(private_key).unwrap(); 618 619 // Prepare the locator. 620 let locator = ("credits.alpha", "transfer_public_to_private"); 621 // Prepare the amount for each call to the function. 622 let amount = 100_000_000u64; 623 // Prepare the function inputs. 624 let inputs = [address.to_string(), format!("{amount}_u64")]; 625 626 // Initialize the process. 627 let process = Process::load().unwrap(); 628 // Create the transactions. 629 let transactions = { 630 Transactions::from_iter((0..2).map(|_| { 631 // Authorize the function. 632 let authorization = 633 process.authorize::<CurrentAlpha, _>(&private_key, locator.0, locator.1, inputs.iter(), rng).unwrap(); 634 // Execute the function. 635 let (_, mut trace) = process.execute::<CurrentAlpha, _>(authorization, rng).unwrap(); 636 637 // Initialize a new block store. 638 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 639 640 // Prepare the assignments. 641 trace.prepare(&Query::from(block_store)).unwrap(); 642 // Compute the proof and construct the execution. 643 let execution = trace.prove_execution::<CurrentAlpha, _>(locator.0, VarunaVersion::V1, rng).unwrap(); 644 // Convert the execution. 645 // Note: This is a testing-only hack to adhere to Rust's dependency cycle rules. 646 let execution = Execution::from_str(&execution.to_string()).unwrap(); 647 648 // Construct the transaction. 649 let transaction = Transaction::from_execution(execution, None).unwrap(); 650 // Prepare the confirmed transaction. 651 ConfirmedTransaction::accepted_execute(0, transaction.clone(), vec![]).unwrap() 652 })) 653 }; 654 655 // Construct the ratifications. 656 let ratifications = Ratifications::try_from(vec![]).unwrap(); 657 658 // Prepare the block header. 659 let header = Header::genesis(&ratifications, &transactions, vec![]) 660 .with_context(|| "Failed to generate genesis sample header") 661 .pretty_unwrap(); 662 // Prepare the previous block hash. 663 let previous_hash = <CurrentNetwork as Network>::BlockHash::default(); 664 665 // Construct the block. 666 let block = Block::new_beacon( 667 &private_key, 668 previous_hash, 669 header, 670 ratifications, 671 None.into(), 672 vec![], 673 transactions.clone(), 674 vec![], 675 rng, 676 ) 677 .unwrap(); 678 assert!(block.header().is_genesis().unwrap(), "Failed to initialize a genesis block"); 679 // Return the block, transaction, and private key. 680 (block, transactions, private_key) 681 }