snarkvm_ledger_test_helpers/
lib.rs

1// Copyright (c) 2019-2025 Provable Inc.
2// This file is part of the snarkVM 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
16extern crate snarkvm_circuit as circuit;
17extern crate snarkvm_console as console;
18
19use console::{
20    account::{Address, PrivateKey},
21    prelude::*,
22    program::{Ciphertext, Literal, Plaintext, ProgramOwner, Record, Value},
23    types::Field,
24};
25use snarkvm_algorithms::snark::varuna::VarunaVersion;
26use snarkvm_ledger_block::{
27    Block,
28    ConfirmedTransaction,
29    Deployment,
30    Execution,
31    Fee,
32    Header,
33    Input,
34    Output,
35    Ratifications,
36    Rejected,
37    Transaction,
38    Transactions,
39    Transition,
40};
41use snarkvm_ledger_query::Query;
42use snarkvm_ledger_store::{BlockStore, helpers::memory::BlockMemory};
43use snarkvm_synthesizer_process::Process;
44use snarkvm_synthesizer_program::Program;
45use snarkvm_utilities::PrettyUnwrap;
46
47use aleo_std::StorageMode;
48use anyhow::Context;
49use std::sync::OnceLock;
50
51type CurrentNetwork = console::network::MainnetV0;
52type CurrentAleo = circuit::network::AleoV0;
53
54/****************************************** Transition ********************************************/
55
56/// Samples a random transition.
57pub 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.
62pub 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.
95pub 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: aleo1d5hg2z3ma00382pngntdp68e74zv54jdxy249qhaujhks9c72yrs33ddah.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
146pub 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"
153program testing_one.aleo;
154
155mapping store:
156    key as u32.public;
157    value as u32.public;
158
159function 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::<CurrentAleo, _>(&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
190pub 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"
197program testing_two.aleo;
198
199mapping store:
200    key as u32.public;
201    value as u32.public;
202
203function 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::<CurrentAleo, _>(&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.
235pub 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.
259pub 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.
273pub 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.
287pub 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.
300pub 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::<CurrentAleo, _>(
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::<CurrentAleo, _>(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::<CurrentAleo, _>(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.
345pub 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.
358pub 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::<CurrentAleo, _>(
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::<CurrentAleo, _>(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::<CurrentAleo, _>(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.
400pub fn small_transaction_program() -> Program<CurrentNetwork> {
401    Program::from_str(
402        r"
403program testing_small.aleo;
404function 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.
415pub fn large_transaction_program() -> Program<CurrentNetwork> {
416    Program::from_str(
417        r"
418program testing_large.aleo;
419function 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.
434pub 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.
473pub 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.
494pub 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 = snarkvm_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::<CurrentAleo, _>(
513                    &private_key,
514                    "testing_large.aleo",
515                    "large_transaction",
516                    Vec::<Value<CurrentNetwork>>::new().iter(),
517                    rng,
518                )
519                .unwrap();
520            // Execute the function.
521            let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
522
523            // Initialize a new block store.
524            let block_store = snarkvm_ledger_store::BlockStore::<
525                CurrentNetwork,
526                snarkvm_ledger_store::helpers::memory::BlockMemory<_>,
527            >::open(StorageMode::new_test(None))
528            .unwrap();
529
530            // Prepare the assignments.
531            trace.prepare(&snarkvm_ledger_query::Query::from(block_store)).unwrap();
532            // Compute the proof and construct the execution.
533            let execution = trace.prove_execution::<CurrentAleo, _>("testing.aleo", 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.
551pub 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.
559pub 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.
569pub 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.
576pub 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.
584pub 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.
595pub 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
603pub 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.
612pub 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.aleo", "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::<CurrentAleo, _>(&private_key, locator.0, locator.1, inputs.iter(), rng).unwrap();
634            // Execute the function.
635            let (_, mut trace) = process.execute::<CurrentAleo, _>(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::<CurrentAleo, _>(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}