1extern 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
54pub fn sample_transition(rng: &mut TestRng) -> Transition<CurrentNetwork> {
58 crate::sample_execution(rng, 0).into_transitions().next().unwrap()
59}
60
61pub fn sample_inputs() -> Vec<(<CurrentNetwork as Network>::TransitionID, Input<CurrentNetwork>)> {
63 let rng = &mut TestRng::default();
64
65 let transaction = crate::sample_execution_transaction_with_fee(true, rng, 0);
67 let transition = transaction.transitions().next().unwrap();
68
69 let transition_id = *transition.id();
71 let input = transition.inputs().iter().next().unwrap().clone();
72
73 let plaintext = Plaintext::Literal(Literal::Field(Uniform::rand(rng)), Default::default());
75 let plaintext_hash = CurrentNetwork::hash_bhp1024(&plaintext.to_bits_le()).unwrap();
76 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
94pub fn sample_outputs() -> Vec<(<CurrentNetwork as Network>::TransitionID, Output<CurrentNetwork>)> {
96 let rng = &mut TestRng::default();
97
98 let transaction = crate::sample_execution_transaction_with_fee(true, rng, 0);
100 let transition = transaction.transitions().next().unwrap();
101
102 let transition_id = *transition.id();
104 let input = transition.outputs().iter().next().unwrap().clone();
105
106 let plaintext = Plaintext::Literal(Literal::Field(Uniform::rand(rng)), Default::default());
108 let plaintext_hash = CurrentNetwork::hash_bhp1024(&plaintext.to_bits_le()).unwrap();
109 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 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 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
144pub 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 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 let process = Process::load().unwrap();
168 let mut deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
170 deployment.set_program_checksum_raw(None);
172 deployment.set_program_owner_raw(None);
174 Deployment::from_str(&deployment.to_string()).unwrap()
177 })
178 .clone();
179 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 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 let process = Process::load().unwrap();
212 let mut deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap();
214 deployment.set_program_checksum_raw(Some(deployment.program().to_checksum()));
216 deployment.set_program_owner_raw(Some(Address::rand(rng)));
218 Deployment::from_str(&deployment.to_string()).unwrap()
221 })
222 .clone();
223 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
234pub fn sample_rejected_deployment(
236 version: u8,
237 edition: u16,
238 is_fee_private: bool,
239 rng: &mut TestRng,
240) -> Rejected<CurrentNetwork> {
241 let deployment = match crate::sample_deployment_transaction(version, edition, is_fee_private, rng) {
243 Transaction::Deploy(_, _, _, deployment, _) => (*deployment).clone(),
244 _ => unreachable!(),
245 };
246
247 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 Rejected::new_deployment(program_owner, deployment)
254}
255
256pub fn sample_execution(rng: &mut TestRng, index: usize) -> Execution<CurrentNetwork> {
260 let block = crate::sample_genesis_block(rng);
262 let transaction = block.transactions().iter().nth(index).unwrap().deref().clone();
264 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
272pub fn sample_rejected_execution(is_fee_private: bool, rng: &mut TestRng) -> Rejected<CurrentNetwork> {
274 let execution = match crate::sample_execution_transaction_with_fee(is_fee_private, rng, 0) {
276 Transaction::Execute(_, _, execution, _) => execution,
277 _ => unreachable!(),
278 };
279
280 Rejected::new_execution(*execution)
282}
283
284pub 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 let deployment_or_execution_id = Field::rand(rng);
293 sample_fee_private(deployment_or_execution_id, rng)
295 })
296 .clone()
297}
298
299pub fn sample_fee_private(deployment_or_execution_id: Field<CurrentNetwork>, rng: &mut TestRng) -> Fee<CurrentNetwork> {
301 let (block, transactions, private_key) = crate::sample_genesis_block_and_components(rng);
303 let credits = transactions.iter().next().unwrap().records().next().unwrap().1.clone();
305 let credits = credits.decrypt(&private_key.try_into().unwrap()).unwrap();
307 let base_fee_in_microcredits = 10_000_000;
309 let priority_fee_in_microcredits = 1_000;
311
312 let process = Process::load().unwrap();
314 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 let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
327
328 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap();
330 block_store.insert(&FromStr::from_str(&block.to_string()).unwrap()).unwrap();
333
334 trace.prepare(&Query::from(block_store)).unwrap();
336 let fee = trace.prove_fee::<CurrentAleo, _>(VarunaVersion::V1, rng).unwrap();
338
339 Fee::from_str(&fee.to_string()).unwrap()
342}
343
344pub 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 let deployment_or_execution_id = Field::rand(rng);
351 sample_fee_public(deployment_or_execution_id, rng)
353 })
354 .clone()
355}
356
357pub fn sample_fee_public(deployment_or_execution_id: Field<CurrentNetwork>, rng: &mut TestRng) -> Fee<CurrentNetwork> {
359 let (block, _, private_key) = crate::sample_genesis_block_and_components(rng);
361 let base_fee_in_microcredits = 10_000_000;
363 let priority_fee_in_microcredits = 1_000;
365
366 let process = Process::load().unwrap();
368 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 let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
380
381 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap();
383 block_store.insert(&FromStr::from_str(&block.to_string()).unwrap()).unwrap();
386
387 trace.prepare(&Query::from(block_store)).unwrap();
389 let fee = trace.prove_fee::<CurrentAleo, _>(VarunaVersion::V1, rng).unwrap();
391
392 Fee::from_str(&fee.to_string()).unwrap()
395}
396
397pub 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
414pub 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
431pub fn sample_deployment_transaction(
435 version: u8,
436 edition: u16,
437 is_fee_private: bool,
438 rng: &mut TestRng,
439) -> Transaction<CurrentNetwork> {
440 let private_key = PrivateKey::new(rng).unwrap();
442 let deployment = match version {
444 1 => sample_deployment_v1(edition, rng),
445 2 => {
446 let mut deployment = sample_deployment_v2(edition, rng);
447 deployment.set_program_checksum_raw(Some(deployment.program().to_checksum()));
449 deployment.set_program_owner_raw(Some(Address::try_from(&private_key).unwrap()));
451 deployment
453 }
454 _ => panic!("Invalid deployment version: {version}"),
455 };
456
457 let deployment_id = deployment.to_deployment_id().unwrap();
459 let owner = ProgramOwner::new(&private_key, deployment_id, rng).unwrap();
461
462 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 Transaction::from_deployment(owner, deployment, fee).unwrap()
470}
471
472pub fn sample_execution_transaction_with_fee(
474 is_fee_private: bool,
475 rng: &mut TestRng,
476 index: usize,
477) -> Transaction<CurrentNetwork> {
478 let execution = crate::sample_execution(rng, index);
480 let execution_id = execution.to_execution_id().unwrap();
482
483 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 Transaction::from_execution(execution, Some(fee)).unwrap()
491}
492
493pub 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 let program = large_transaction_program();
501
502 let mut process = snarkvm_synthesizer_process::Process::load().unwrap();
504 process.add_program(&program).unwrap();
506
507 let private_key = PrivateKey::new(rng).unwrap();
509
510 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 let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
522
523 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 trace.prepare(&snarkvm_ledger_query::Query::from(block_store)).unwrap();
532 let execution = trace.prove_execution::<CurrentAleo, _>("testing.aleo", VarunaVersion::V1, rng).unwrap();
534 Execution::from_bytes_le(&execution.to_bytes_le().unwrap()).unwrap()
537 })
538 .clone();
539
540 let execution_id = execution.to_execution_id().unwrap();
542
543 let fee = crate::sample_fee_public(execution_id, rng);
545
546 Transaction::from_execution(execution, Some(fee)).unwrap()
548}
549
550pub fn sample_fee_private_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
552 let fee = crate::sample_fee_private_hardcoded(rng);
554 Transaction::from_fee(fee).unwrap()
556}
557
558pub fn sample_fee_public_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
560 let fee = crate::sample_fee_public_hardcoded(rng);
562 Transaction::from_fee(fee).unwrap()
564}
565
566pub fn sample_block_transactions(rng: &mut TestRng) -> Transactions<CurrentNetwork> {
570 crate::sample_genesis_block(rng).transactions().clone()
571}
572
573pub fn sample_genesis_block(rng: &mut TestRng) -> Block<CurrentNetwork> {
577 let (block, _, _) = crate::sample_genesis_block_and_components(rng);
579 block
581}
582
583pub fn sample_genesis_block_and_transactions(
585 rng: &mut TestRng,
586) -> (Block<CurrentNetwork>, Transactions<CurrentNetwork>) {
587 let (block, transactions, _) = crate::sample_genesis_block_and_components(rng);
589 (block, transactions)
591}
592
593pub 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 PrivateKey::<CurrentNetwork>::new(rng).unwrap()
608 })
609}
610
611pub fn sample_genesis_block_and_components_uncached(
613 rng: &mut TestRng,
614) -> (Block<CurrentNetwork>, Transactions<CurrentNetwork>, PrivateKey<CurrentNetwork>) {
615 let private_key = sample_genesis_private_key(rng);
617 let address = Address::<CurrentNetwork>::try_from(private_key).unwrap();
618
619 let locator = ("credits.aleo", "transfer_public_to_private");
621 let amount = 100_000_000u64;
623 let inputs = [address.to_string(), format!("{amount}_u64")];
625
626 let process = Process::load().unwrap();
628 let transactions = {
630 Transactions::from_iter((0..2).map(|_| {
631 let authorization =
633 process.authorize::<CurrentAleo, _>(&private_key, locator.0, locator.1, inputs.iter(), rng).unwrap();
634 let (_, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap();
636
637 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap();
639
640 trace.prepare(&Query::from(block_store)).unwrap();
642 let execution = trace.prove_execution::<CurrentAleo, _>(locator.0, VarunaVersion::V1, rng).unwrap();
644 let execution = Execution::from_str(&execution.to_string()).unwrap();
647
648 let transaction = Transaction::from_execution(execution, None).unwrap();
650 ConfirmedTransaction::accepted_execute(0, transaction.clone(), vec![]).unwrap()
652 }))
653 };
654
655 let ratifications = Ratifications::try_from(vec![]).unwrap();
657
658 let header = Header::genesis(&ratifications, &transactions, vec![])
660 .with_context(|| "Failed to generate genesis sample header")
661 .pretty_unwrap();
662 let previous_hash = <CurrentNetwork as Network>::BlockHash::default();
664
665 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 (block, transactions, private_key)
681}