/ ledger / test-helpers / src / lib.rs
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  }