test_execute.rs
1 // Copyright (c) 2025 ADnet Contributors 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 use crate::{CallStack, InclusionVersion, Process, Trace, execution_cost, execution_cost_for_authorization}; 17 use alphavm_algorithms::snark::varuna::VarunaVersion; 18 use alphavm_ledger_block::{Fee, Output, Transaction, Transition}; 19 use alphavm_ledger_query::Query; 20 use alphavm_ledger_store::{ 21 BlockStorage, BlockStore, FinalizeStorage, FinalizeStore, 22 helpers::memory::{BlockMemory, FinalizeMemory}, 23 }; 24 use alphavm_synthesizer_program::{FinalizeGlobalState, FinalizeStoreTrait, Program, StackTrait}; 25 use alphavm_synthesizer_snark::UniversalSRS; 26 use circuit::{Aleo, network::AleoV0}; 27 use console::{ 28 account::{Address, PrivateKey, ViewKey}, 29 network::{MainnetV0, prelude::*}, 30 program::{Identifier, Literal, Plaintext, ProgramID, Record, Value}, 31 types::{Field, U64}, 32 }; 33 34 use alpha_std::StorageMode; 35 #[cfg(feature = "locktick")] 36 use locktick::parking_lot::RwLock; 37 #[cfg(not(feature = "locktick"))] 38 use parking_lot::RwLock; 39 use std::sync::Arc; 40 41 type CurrentNetwork = MainnetV0; 42 type CurrentAleo = AleoV0; 43 44 /// Samples a new finalize state. 45 pub fn sample_finalize_state(block_height: u32) -> FinalizeGlobalState { 46 FinalizeGlobalState::from(block_height as u64, block_height, None, [0u8; 32]) 47 } 48 49 /// Samples a valid fee for the given process, block store, and finalize store. 50 pub fn sample_fee<N: Network, A: Aleo<Network = N>, B: BlockStorage<N>, P: FinalizeStorage<N>>( 51 process: &Process<N>, 52 block_store: &BlockStore<N, B>, 53 finalize_store: &FinalizeStore<N, P>, 54 rng: &mut TestRng, 55 ) -> Fee<N> { 56 let program_id = ProgramID::from_str("credits.alpha").unwrap(); 57 let account_mapping = Identifier::from_str("account").unwrap(); 58 59 // Initialize the account mapping, even if it already has been (we silence the result for testing). 60 let _ = finalize_store.initialize_mapping(program_id, account_mapping); 61 62 // Sample a random private key. 63 let private_key = PrivateKey::<N>::new(rng).unwrap(); 64 let address = Address::try_from(private_key).unwrap(); 65 66 // Construct the key. 67 let key = Plaintext::from(Literal::Address(address)); 68 // Construct the public balance. 69 let value = Value::from(Literal::U64(U64::new(100))); 70 // Update the public balance in finalize storage. 71 finalize_store.update_key_value(program_id, account_mapping, key, value).unwrap(); 72 73 // Sample a base fee in microcredits. 74 let base_fee_in_microcredits = 100; 75 // Sample a priority fee in microcredits. 76 let priority_fee_in_microcredits = 0; 77 // Sample a dummy ID. 78 let id = Field::rand(rng); 79 80 // Authorize the fee. 81 let authorization = process 82 .authorize_fee_public::<A, _>(&private_key, base_fee_in_microcredits, priority_fee_in_microcredits, id, rng) 83 .unwrap(); 84 // Execute the fee. 85 let (_, mut trace) = process.execute::<A, _>(authorization, rng).unwrap(); 86 // Prepare the assignments. 87 trace.prepare(&Query::from(block_store)).unwrap(); 88 // Compute the proof and construct the fee. 89 trace.prove_fee::<A, _>(VarunaVersion::V2, rng).unwrap() 90 } 91 92 #[test] 93 fn test_program_evaluate_function() { 94 let program = Program::<CurrentNetwork>::from_str( 95 r" 96 program example.alpha; 97 98 function foo: 99 input r0 as field.public; 100 input r1 as field.private; 101 add r0 r1 into r2; 102 output r2 as field.private; 103 ", 104 ) 105 .unwrap(); 106 107 // Declare the function name. 108 let function_name = Identifier::from_str("foo").unwrap(); 109 // Declare the function inputs. 110 let inputs = [ 111 Value::<CurrentNetwork>::Plaintext(Plaintext::from_str("2field").unwrap()), 112 Value::Plaintext(Plaintext::from_str("3field").unwrap()), 113 ]; 114 115 // Construct the process. 116 let process = crate::test_helpers::sample_process(&program); 117 118 // Initialize an RNG. 119 let rng = &mut TestRng::default(); 120 121 // Compute the authorization. 122 let authorization = { 123 // Initialize caller private key. 124 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 125 126 // Authorize the function call. 127 let authorization = process 128 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, inputs.iter(), rng) 129 .unwrap(); 130 assert_eq!(authorization.len(), 1); 131 authorization 132 }; 133 134 // Retrieve the stack. 135 let stack = process.get_stack(program.id()).unwrap(); 136 137 // Declare the expected output. 138 let expected = Value::Plaintext(Plaintext::<CurrentNetwork>::from_str("5field").unwrap()); 139 140 // Run the function. 141 let response = stack 142 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization.replicate()).unwrap(), None, None, rng) 143 .unwrap(); 144 let candidate = response.outputs(); 145 assert_eq!(1, candidate.len()); 146 assert_eq!(expected, candidate[0]); 147 148 // Re-run to ensure state continues to work. 149 let response = stack 150 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization).unwrap(), None, None, rng) 151 .unwrap(); 152 let candidate = response.outputs(); 153 assert_eq!(1, candidate.len()); 154 assert_eq!(expected, candidate[0]); 155 } 156 157 #[test] 158 fn test_program_evaluate_struct_and_function() { 159 // Initialize a new program. 160 let (string, program) = Program::<CurrentNetwork>::parse( 161 r" 162 program example.alpha; 163 164 struct message: 165 first as field; 166 second as field; 167 168 function compute: 169 input r0 as message.private; 170 add r0.first r0.second into r1; 171 output r1 as field.private;", 172 ) 173 .unwrap(); 174 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 175 176 // Declare the function name. 177 let function_name = Identifier::from_str("compute").unwrap(); 178 // Declare the input value. 179 let input = Value::<CurrentNetwork>::Plaintext(Plaintext::from_str("{ first: 2field, second: 3field }").unwrap()); 180 // Declare the expected output value. 181 let expected = Value::Plaintext(Plaintext::from_str("5field").unwrap()); 182 183 // Construct the process. 184 let process = crate::test_helpers::sample_process(&program); 185 186 // Initialize an RNG. 187 let rng = &mut TestRng::default(); 188 189 // Compute the authorization. 190 let authorization = { 191 // Initialize caller private key. 192 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 193 194 // Authorize the function call. 195 let authorization = process 196 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [input].iter(), rng) 197 .unwrap(); 198 assert_eq!(authorization.len(), 1); 199 authorization 200 }; 201 202 // Retrieve the stack. 203 let stack = process.get_stack(program.id()).unwrap(); 204 205 // Compute the output value. 206 let response = stack 207 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization.replicate()).unwrap(), None, None, rng) 208 .unwrap(); 209 let candidate = response.outputs(); 210 assert_eq!(1, candidate.len()); 211 assert_eq!(expected, candidate[0]); 212 213 // Re-run to ensure state continues to work. 214 let response = stack 215 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization).unwrap(), None, None, rng) 216 .unwrap(); 217 let candidate = response.outputs(); 218 assert_eq!(1, candidate.len()); 219 assert_eq!(expected, candidate[0]); 220 } 221 222 #[test] 223 fn test_program_evaluate_record_and_function() { 224 // Initialize a new program. 225 let (string, program) = Program::<CurrentNetwork>::parse( 226 r" 227 program token.alpha; 228 229 record token: 230 owner as address.private; 231 token_amount as u64.private; 232 233 function compute: 234 input r0 as token.record; 235 add r0.token_amount r0.token_amount into r1; 236 output r1 as u64.private;", 237 ) 238 .unwrap(); 239 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 240 241 // Declare the function name. 242 let function_name = Identifier::from_str("compute").unwrap(); 243 244 // Initialize an RNG. 245 let rng = &mut TestRng::default(); 246 247 // Initialize caller private key. 248 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 249 let caller = Address::try_from(&caller_private_key).unwrap(); 250 251 // Declare the input value. 252 let input_record = Record::from_str(&format!( 253 "{{ owner: {caller}.private, token_amount: 100u64.private, _nonce: 0group.public }}" 254 )) 255 .unwrap(); 256 let input = Value::<CurrentNetwork>::Record(input_record); 257 258 // Declare the expected output value. 259 let expected = Value::Plaintext(Plaintext::from_str("200u64").unwrap()); 260 261 // Construct the process. 262 let process = crate::test_helpers::sample_process(&program); 263 264 // Authorize the function call. 265 let authorization = process 266 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [input].iter(), rng) 267 .unwrap(); 268 assert_eq!(authorization.len(), 1); 269 270 // Retrieve the stack. 271 let stack = process.get_stack(program.id()).unwrap(); 272 273 // Compute the output value. 274 let response = stack 275 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization.replicate()).unwrap(), None, None, rng) 276 .unwrap(); 277 let candidate = response.outputs(); 278 assert_eq!(1, candidate.len()); 279 assert_eq!(expected, candidate[0]); 280 281 // Re-run to ensure state continues to work. 282 let response = stack 283 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization).unwrap(), None, None, rng) 284 .unwrap(); 285 let candidate = response.outputs(); 286 assert_eq!(1, candidate.len()); 287 assert_eq!(expected, candidate[0]); 288 } 289 290 #[test] 291 fn test_program_evaluate_call() { 292 // Initialize a new program. 293 let (string, program) = Program::<CurrentNetwork>::parse( 294 r" 295 program example_call.alpha; 296 297 // (a + (a + b)) + (a + b) == (3a + 2b) 298 closure execute: 299 input r0 as field; 300 input r1 as field; 301 add r0 r1 into r2; 302 add r0 r2 into r3; 303 add r2 r3 into r4; 304 output r4 as field; 305 output r3 as field; 306 output r2 as field; 307 308 function compute: 309 input r0 as field.private; 310 input r1 as field.public; 311 call execute r0 r1 into r2 r3 r4; 312 output r2 as field.private; 313 output r3 as field.private; 314 output r4 as field.private;", 315 ) 316 .unwrap(); 317 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 318 319 // Declare the function name. 320 let function_name = Identifier::from_str("compute").unwrap(); 321 322 // Declare the input value. 323 let r0 = Value::<CurrentNetwork>::Plaintext(Plaintext::from_str("3field").unwrap()); 324 let r1 = Value::<CurrentNetwork>::Plaintext(Plaintext::from_str("5field").unwrap()); 325 326 // Declare the expected output value. 327 let r2 = Value::Plaintext(Plaintext::from_str("19field").unwrap()); 328 let r3 = Value::Plaintext(Plaintext::from_str("11field").unwrap()); 329 let r4 = Value::Plaintext(Plaintext::from_str("8field").unwrap()); 330 331 { 332 // Construct the process. 333 let process = crate::test_helpers::sample_process(&program); 334 // Check that the circuit key can be synthesized. 335 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, &mut TestRng::default()).unwrap(); 336 } 337 338 // Construct the process. 339 let process = crate::test_helpers::sample_process(&program); 340 341 // Initialize an RNG. 342 let rng = &mut TestRng::default(); 343 344 // Compute the authorization. 345 let authorization = { 346 // Initialize caller private key. 347 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 348 349 // Authorize the function call. 350 let authorization = process 351 .authorize::<CurrentAleo, _>( 352 &caller_private_key, 353 program.id(), 354 function_name, 355 [r0.clone(), r1.clone()].iter(), 356 rng, 357 ) 358 .unwrap(); 359 assert_eq!(authorization.len(), 1); 360 authorization 361 }; 362 363 // Retrieve the stack. 364 let stack = process.get_stack(program.id()).unwrap(); 365 366 // Compute the output value. 367 let response = stack 368 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization.replicate()).unwrap(), None, None, rng) 369 .unwrap(); 370 let candidate = response.outputs(); 371 assert_eq!(3, candidate.len()); 372 assert_eq!(r2, candidate[0]); 373 assert_eq!(r3, candidate[1]); 374 assert_eq!(r4, candidate[2]); 375 376 // Re-run to ensure state continues to work. 377 let response = stack 378 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization).unwrap(), None, None, rng) 379 .unwrap(); 380 let candidate = response.outputs(); 381 assert_eq!(3, candidate.len()); 382 assert_eq!(r2, candidate[0]); 383 assert_eq!(r3, candidate[1]); 384 assert_eq!(r4, candidate[2]); 385 386 use circuit::Environment; 387 388 // Ensure the environment is clean. 389 assert_eq!(0, CurrentAleo::num_constants()); 390 assert_eq!(1, CurrentAleo::num_public()); 391 assert_eq!(0, CurrentAleo::num_private()); 392 assert_eq!(0, CurrentAleo::num_constraints()); 393 394 // Initialize an RNG. 395 let rng = &mut TestRng::default(); 396 // Initialize a burner private key. 397 let burner_private_key = PrivateKey::new(rng).unwrap(); 398 // Authorize the function call, with a burner private key. 399 let authorization = process 400 .authorize::<CurrentAleo, _>(&burner_private_key, program.id(), function_name, [r0, r1].iter(), rng) 401 .unwrap(); 402 assert_eq!(authorization.len(), 1); 403 404 // Re-run to ensure state continues to work. 405 let trace = Arc::new(RwLock::new(Trace::new())); 406 let call_stack = CallStack::execute(authorization, trace).unwrap(); 407 let response = stack.execute_function::<CurrentAleo, _>(call_stack, None, None, rng).unwrap(); 408 let candidate = response.outputs(); 409 assert_eq!(3, candidate.len()); 410 assert_eq!(r2, candidate[0]); 411 assert_eq!(r3, candidate[1]); 412 assert_eq!(r4, candidate[2]); 413 } 414 415 #[test] 416 fn test_program_evaluate_cast() { 417 // Initialize a new program. 418 let (string, program) = Program::<CurrentNetwork>::parse( 419 r" 420 program token_with_cast.alpha; 421 422 record token: 423 owner as address.private; 424 token_amount as u64.private; 425 426 function compute: 427 input r0 as token.record; 428 cast r0.owner r0.token_amount into r1 as token.record; 429 output r1 as token.record;", 430 ) 431 .unwrap(); 432 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 433 434 // Declare the function name. 435 let function_name = Identifier::from_str("compute").unwrap(); 436 437 // Initialize an RNG. 438 let rng = &mut TestRng::default(); 439 440 // Initialize caller private key. 441 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 442 let caller = Address::try_from(&caller_private_key).unwrap(); 443 444 // Declare the input value. 445 let input_record = Record::from_str(&format!( 446 "{{ owner: {caller}.private, token_amount: 100u64.private, _nonce: 0group.public }}" 447 )) 448 .unwrap(); 449 let input = Value::<CurrentNetwork>::Record(input_record); 450 451 // Construct the process. 452 let process = crate::test_helpers::sample_process(&program); 453 454 // Authorize the function call. 455 let authorization = process 456 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [input].iter(), rng) 457 .unwrap(); 458 assert_eq!(authorization.len(), 1); 459 let request = authorization.peek_next().unwrap(); 460 461 // Compute the encryption randomizer as `HashToScalar(tvk || index)`. 462 let randomizer = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(1)]).unwrap(); 463 let nonce = CurrentNetwork::g_scalar_multiply(&randomizer); 464 465 // Declare the expected output value. 466 let expected = Value::from_str(&format!( 467 "{{ owner: {caller}.private, token_amount: 100u64.private, _nonce: {nonce}.public, _version: 1u8.public }}" 468 )) 469 .unwrap(); 470 471 // Retrieve the stack. 472 let stack = process.get_stack(program.id()).unwrap(); 473 474 // Compute the output value. 475 let response = stack 476 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization.replicate()).unwrap(), None, None, rng) 477 .unwrap(); 478 let candidate = response.outputs(); 479 assert_eq!(1, candidate.len()); 480 assert_eq!(expected, candidate[0]); 481 482 // Re-run to ensure state continues to work. 483 let response = stack 484 .evaluate_function::<CurrentAleo, _>(CallStack::evaluate(authorization).unwrap(), None, None, rng) 485 .unwrap(); 486 let candidate = response.outputs(); 487 assert_eq!(1, candidate.len()); 488 assert_eq!(expected, candidate[0]); 489 } 490 491 #[test] 492 fn test_process_execute_transfer_public_to_private() { 493 // Initialize a new program. 494 let program = Program::<CurrentNetwork>::credits().unwrap(); 495 496 // Initialize the RNG. 497 let rng = &mut TestRng::default(); 498 // Initialize a new caller account. 499 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 500 let caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 501 let caller = Address::try_from(&caller_private_key).unwrap(); 502 // Initialize a new recipient address. 503 let recipient_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 504 let recipient_view_key = ViewKey::try_from(&recipient_private_key).unwrap(); 505 let recipient = Address::try_from(&recipient_private_key).unwrap(); 506 // Declare the input value. 507 let r0 = Value::<CurrentNetwork>::from_str(&format!("{recipient}")).unwrap(); 508 let r1 = Value::<CurrentNetwork>::from_str("99_000_000_000_000_u64").unwrap(); 509 510 // Construct the process. 511 let process = Process::load().unwrap(); 512 513 // Authorize the function call. 514 let authorization = process 515 .authorize::<CurrentAleo, _>( 516 &caller_private_key, 517 program.id(), 518 Identifier::from_str("transfer_public_to_private").unwrap(), 519 [r0, r1].iter(), 520 rng, 521 ) 522 .unwrap(); 523 assert_eq!(authorization.len(), 1); 524 let request = authorization.peek_next().unwrap(); 525 526 // Compute the encryption randomizer as `HashToScalar(tvk || index)`. 527 let randomizer = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(2)]).unwrap(); 528 let nonce = CurrentNetwork::g_scalar_multiply(&randomizer); 529 530 // Declare the expected output value. 531 let r2 = Value::from_str(&format!( 532 "{{ owner: {recipient}.private, microcredits: 99_000_000_000_000_u64.private, _nonce: {nonce}.public, _version: 1u8.public }}" 533 )) 534 .unwrap(); 535 536 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 537 assert_eq!(authorization.len(), 1); 538 539 // Compute the output value. 540 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 541 let candidate = response.outputs(); 542 assert_eq!(2, candidate.len()); 543 assert_eq!(r2, candidate[0]); 544 545 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 546 assert_eq!(authorization.len(), 1); 547 548 let expected_execution_cost = 549 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 550 551 // Execute the request. 552 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 553 let candidate = response.outputs(); 554 assert_eq!(2, candidate.len()); 555 assert_eq!(r2, candidate[0]); 556 557 // Check that the sender ciphertext is well-formed. 558 { 559 // Construct a new process. 560 let process = Process::load().unwrap(); 561 // Initialize a new block store. 562 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 563 // Prepare the trace. 564 trace.prepare(&Query::from(block_store)).unwrap(); 565 // Prove the execution. 566 let execution = trace.prove_execution::<CurrentAleo, _>("credits.alpha", VarunaVersion::V2, rng).unwrap(); 567 // Verify the execution. 568 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 569 570 // Check the execution cost 571 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 572 573 // Ensure there is only one transition. 574 assert_eq!(1, execution.transitions().len()); 575 // Retrieve the transition. 576 let transition: Transition<_> = execution.into_transitions().next().unwrap(); 577 // Ensure the transition program ID and function name are correct. 578 assert_eq!(transition.program_id(), program.id()); 579 assert_eq!(transition.function_name(), &Identifier::from_str("transfer_public_to_private").unwrap()); 580 // Ensure the transition has 2 inputs and 2 outputs. 581 assert_eq!(2, transition.inputs().len()); 582 assert_eq!(2, transition.outputs().len()); 583 // Ensure the first output is a record. 584 assert!(matches!(transition.outputs()[0], Output::Record(..))); 585 586 // Retrieve the first output. 587 let output = transition.outputs()[0].clone(); 588 // Decrypt the sender ciphertext. 589 let expected_caller = output.decrypt_sender_ciphertext(&recipient_view_key).unwrap(); 590 // Ensure the caller address matches the expected caller. 591 assert_eq!(Some(caller), expected_caller); 592 593 // Ensure decryption fails with the caller view key. 594 assert!(output.decrypt_sender_ciphertext(&caller_view_key).is_err()); 595 596 // Ensure decryption fails with a different view key. 597 let different_view_key = ViewKey::try_from(&PrivateKey::<CurrentNetwork>::new(rng).unwrap()).unwrap(); 598 assert!(output.decrypt_sender_ciphertext(&different_view_key).is_err()); 599 } 600 601 // use circuit::Environment; 602 // 603 // assert_eq!(22152, CurrentAleo::num_constants()); 604 // assert_eq!(9, CurrentAleo::num_public()); 605 // assert_eq!(20561, CurrentAleo::num_private()); 606 // assert_eq!(20579, CurrentAleo::num_constraints()); 607 // assert_eq!(79386, CurrentAleo::num_gates()); 608 } 609 610 #[test] 611 fn test_process_circuit_key() { 612 // Initialize a new program. 613 let program = Program::<CurrentNetwork>::from_str( 614 r#"program testing.alpha; 615 616 function hello_world: 617 input r0 as u32.public; 618 input r1 as u32.private; 619 add r0 r1 into r2; 620 output r2 as u32.private; 621 "#, 622 ) 623 .unwrap(); 624 625 // Declare the function name. 626 let function_name = Identifier::from_str("hello_world").unwrap(); 627 628 // Construct the process. 629 let process = crate::test_helpers::sample_process(&program); 630 // Check that the circuit key can be synthesized. 631 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, &mut TestRng::default()).unwrap(); 632 } 633 634 #[test] 635 fn test_process_multirecords() { 636 // Initialize a new program. 637 let program = Program::<CurrentNetwork>::from_str( 638 r"program multirecord.alpha; 639 640 record record_a: 641 owner as address.private; 642 item as u64.private; 643 644 record record_b: 645 owner as address.private; 646 item as u64.private; 647 648 record record_c: 649 owner as address.private; 650 item as u64.private; 651 652 function initialize: 653 input r0 as record_a.record; 654 input r1 as record_b.record; 655 input r2 as record_c.record; 656 cast r0.owner r0.item into r3 as record_a.record; 657 cast r1.owner r1.item into r4 as record_b.record; 658 cast r2.owner r2.item into r5 as record_c.record; 659 output r3 as record_a.record; 660 output r4 as record_b.record; 661 output r5 as record_c.record;", 662 ) 663 .unwrap(); 664 665 // Declare the function name. 666 let function_name = Identifier::from_str("initialize").unwrap(); 667 668 // Initialize the RNG. 669 let rng = &mut TestRng::default(); 670 671 // Construct the process. 672 let process = crate::test_helpers::sample_process(&program); 673 674 // Initialize a new caller account. 675 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 676 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 677 let caller = Address::try_from(&caller_private_key).unwrap(); 678 679 // Declare the input value. 680 let input_a = 681 Value::from_str(&format!("{{ owner: {caller}.private, item: 1234u64.private, _nonce: 0group.public }}")) 682 .unwrap(); 683 let input_b = 684 Value::from_str(&format!("{{ owner: {caller}.private, item: 4321u64.private, _nonce: 0group.public }}")) 685 .unwrap(); 686 let input_c = 687 Value::from_str(&format!("{{ owner: {caller}.private, item: 5678u64.private, _nonce: 0group.public }}")) 688 .unwrap(); 689 690 // Authorize the function call. 691 let authorization = process 692 .authorize::<CurrentAleo, _>( 693 &caller_private_key, 694 program.id(), 695 function_name, 696 [input_a, input_b, input_c].iter(), 697 rng, 698 ) 699 .unwrap(); 700 assert_eq!(authorization.len(), 1); 701 let request = authorization.peek_next().unwrap(); 702 703 // Compute the encryption randomizer for the first output as `HashToScalar(tvk || index)`. 704 let randomizer_a = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(3)]).unwrap(); 705 let nonce_a = CurrentNetwork::g_scalar_multiply(&randomizer_a); 706 707 // Compute the encryption randomizer for the second output as `HashToScalar(tvk || index)`. 708 let randomizer_b = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(4)]).unwrap(); 709 let nonce_b = CurrentNetwork::g_scalar_multiply(&randomizer_b); 710 711 // Compute the encryption randomizer for the third output as `HashToScalar(tvk || index)`. 712 let randomizer_c = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(5)]).unwrap(); 713 let nonce_c = CurrentNetwork::g_scalar_multiply(&randomizer_c); 714 715 // Declare the output value. 716 let output_a = Value::from_str(&format!( 717 "{{ owner: {caller}.private, item: 1234u64.private, _nonce: {nonce_a}.public, _version: 1u8.public }}" 718 )) 719 .unwrap(); 720 let output_b = Value::from_str(&format!( 721 "{{ owner: {caller}.private, item: 4321u64.private, _nonce: {nonce_b}.public, _version: 1u8.public }}" 722 )) 723 .unwrap(); 724 let output_c = Value::from_str(&format!( 725 "{{ owner: {caller}.private, item: 5678u64.private, _nonce: {nonce_c}.public, _version: 1u8.public }}" 726 )) 727 .unwrap(); 728 729 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 730 assert_eq!(authorization.len(), 1); 731 732 // Compute the output value. 733 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 734 let candidate = response.outputs(); 735 assert_eq!(3, candidate.len()); 736 assert_eq!(output_a, candidate[0]); 737 assert_eq!(output_b, candidate[1]); 738 assert_eq!(output_c, candidate[2]); 739 740 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 741 assert_eq!(authorization.len(), 1); 742 743 // Execute the request. 744 let (response, _trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 745 let candidate = response.outputs(); 746 assert_eq!(3, candidate.len()); 747 assert_eq!(output_a, candidate[0]); 748 assert_eq!(output_b, candidate[1]); 749 assert_eq!(output_c, candidate[2]); 750 751 // use circuit::Environment; 752 // 753 // assert_eq!(20060, CurrentAleo::num_constants()); 754 // assert_eq!(12, CurrentAleo::num_public()); 755 // assert_eq!(57602, CurrentAleo::num_private()); 756 // assert_eq!(57684, CurrentAleo::num_constraints()); 757 // assert_eq!(178189, CurrentAleo::num_gates()); 758 } 759 760 #[test] 761 fn test_process_self_caller() { 762 // Initialize a new program. 763 let program = Program::<CurrentNetwork>::from_str( 764 r"program caller.alpha; 765 766 record data: 767 owner as address.private; 768 item as u64.private; 769 770 function initialize: 771 input r0 as data.record; 772 cast self.caller r0.item into r1 as data.record; 773 output r1 as data.record;", 774 ) 775 .unwrap(); 776 777 // Declare the function name. 778 let function_name = Identifier::from_str("initialize").unwrap(); 779 780 // Initialize the RNG. 781 let rng = &mut TestRng::default(); 782 783 // Construct the process. 784 let process = crate::test_helpers::sample_process(&program); 785 786 // Initialize a new caller account. 787 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 788 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 789 let caller = Address::try_from(&caller_private_key).unwrap(); 790 791 // Declare the input value. 792 let input = 793 Value::from_str(&format!("{{ owner: {caller}.private, item: 1234u64.private, _nonce: 0group.public }}")) 794 .unwrap(); 795 796 // Authorize the function call. 797 let authorization = process 798 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [input].iter(), rng) 799 .unwrap(); 800 assert_eq!(authorization.len(), 1); 801 let request = authorization.peek_next().unwrap(); 802 803 // Compute the encryption randomizer as `HashToScalar(tvk || index)`. 804 let randomizer = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(1)]).unwrap(); 805 let nonce = CurrentNetwork::g_scalar_multiply(&randomizer); 806 807 // Declare the output value. 808 let output = Value::from_str(&format!( 809 "{{ owner: {caller}.private, item: 1234u64.private, _nonce: {nonce}.public, _version: 1u8.public }}" 810 )) 811 .unwrap(); 812 813 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 814 assert_eq!(authorization.len(), 1); 815 816 // Compute the output value. 817 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 818 let candidate = response.outputs(); 819 assert_eq!(1, candidate.len()); 820 assert_eq!(output, candidate[0]); 821 822 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 823 assert_eq!(authorization.len(), 1); 824 825 // Execute the request. 826 let (response, _trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 827 let candidate = response.outputs(); 828 assert_eq!(1, candidate.len()); 829 assert_eq!(output, candidate[0]); 830 } 831 832 #[test] 833 fn test_process_program_id() { 834 // Initialize a new program. 835 let program = Program::<CurrentNetwork>::from_str( 836 r"program id.alpha; 837 838 struct data: 839 user as address; 840 841 function initialize: 842 cast id.alpha into r0 as data; 843 output r0 as data.private;", 844 ) 845 .unwrap(); 846 847 // Declare the program ID. 848 let program_id = ProgramID::from_str("id.alpha").unwrap(); 849 assert_eq!(*program.id(), program_id); 850 851 // Declare the function name. 852 let function_name = Identifier::from_str("initialize").unwrap(); 853 854 // Initialize the RNG. 855 let rng = &mut TestRng::default(); 856 857 // Construct the process. 858 let process = crate::test_helpers::sample_process(&program); 859 860 // Initialize a new caller account. 861 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 862 863 // Authorize the function call. 864 let inputs: &[Value<CurrentNetwork>] = &[]; 865 let authorization = process 866 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, inputs.iter(), rng) 867 .unwrap(); 868 assert_eq!(authorization.len(), 1); 869 870 // Declare the output value. 871 let output = Value::from_str(&format!("{{ user: {} }}", program_id.to_address().unwrap())).unwrap(); 872 873 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 874 assert_eq!(authorization.len(), 1); 875 876 // Compute the output value. 877 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 878 let candidate = response.outputs(); 879 assert_eq!(1, candidate.len()); 880 assert_eq!(output, candidate[0]); 881 882 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 883 assert_eq!(authorization.len(), 1); 884 885 // Execute the request. 886 let (response, _trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 887 let candidate = response.outputs(); 888 assert_eq!(1, candidate.len()); 889 assert_eq!(output, candidate[0]); 890 } 891 892 #[test] 893 fn test_process_output_operand() { 894 // Helper function to test authorization, execution, and verification for the program below. 895 fn authorize_execute_and_verify( 896 program: &Program<CurrentNetwork>, 897 function_name: Identifier<CurrentNetwork>, 898 output: Value<CurrentNetwork>, 899 caller_private_key: &PrivateKey<CurrentNetwork>, 900 rng: &mut TestRng, 901 ) { 902 // Construct the process. 903 let process = crate::test_helpers::sample_process(program); 904 905 // Authorize the function call. 906 let inputs: &[Value<CurrentNetwork>] = &[]; 907 let authorization = process 908 .authorize::<CurrentAleo, _>(caller_private_key, program.id(), function_name, inputs.iter(), rng) 909 .unwrap(); 910 assert_eq!(authorization.len(), 1); 911 912 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 913 assert_eq!(authorization.len(), 1); 914 915 // Compute the output value. 916 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 917 let candidate = response.outputs(); 918 assert_eq!(1, candidate.len()); 919 assert_eq!(output, candidate[0]); 920 921 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 922 assert_eq!(authorization.len(), 1); 923 924 // Execute the request. 925 let (response, _trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 926 let candidate = response.outputs(); 927 assert_eq!(1, candidate.len()); 928 assert_eq!(output, candidate[0]); 929 930 // process.verify_execution::<true>(&execution).unwrap(); 931 } 932 933 // Initialize a new program. 934 let program = Program::<CurrentNetwork>::from_str( 935 r"program operand.alpha; 936 937 function program_id: 938 output operand.alpha as address.private; 939 940 function literal: 941 output 1234u64 as u64.private; 942 943 function caller: 944 output self.caller as address.private;", 945 ) 946 .unwrap(); 947 948 // Initialize the RNG. 949 let rng = &mut TestRng::default(); 950 951 // Initialize a new caller account. 952 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 953 let caller = Address::try_from(&caller_private_key).unwrap(); 954 955 // Test the `program_id` function. 956 authorize_execute_and_verify( 957 &program, 958 Identifier::from_str("program_id").unwrap(), 959 Value::from_str(&program.id().to_address().unwrap().to_string()).unwrap(), 960 &caller_private_key, 961 rng, 962 ); 963 964 // Test the `literal` function. 965 authorize_execute_and_verify( 966 &program, 967 Identifier::from_str("literal").unwrap(), 968 Value::from_str("1234u64").unwrap(), 969 &caller_private_key, 970 rng, 971 ); 972 973 // Test the `caller` function. 974 authorize_execute_and_verify( 975 &program, 976 Identifier::from_str("caller").unwrap(), 977 Value::from_str(&format!("{caller}")).unwrap(), 978 &caller_private_key, 979 rng, 980 ); 981 } 982 983 #[test] 984 fn test_process_execute_call_closure() { 985 // Initialize a new program. 986 let (string, program) = Program::<CurrentNetwork>::parse( 987 r" 988 program token.alpha; 989 990 record token: 991 owner as address.private; 992 token_amount as u64.private; 993 994 // (a + (a + b)) + (a + b) == (3a + 2b) 995 closure execute: 996 input r0 as field; 997 input r1 as field; 998 add r0 r1 into r2; 999 add r0 r2 into r3; 1000 add r2 r3 into r4; 1001 output r4 as field; 1002 output r3 as field; 1003 output r2 as field; 1004 1005 closure check_not_equal: 1006 input r0 as field; 1007 input r1 as field; 1008 assert.neq r0 r1; 1009 1010 function compute: 1011 input r0 as field.private; 1012 input r1 as field.public; 1013 input r2 as token.record; 1014 cast r2.owner r2.token_amount into r3 as token.record; 1015 call check_not_equal r0 r1; 1016 call execute r0 r1 into r4 r5 r6; 1017 output r3 as token.record; 1018 output r4 as field.private; 1019 output r5 as field.private; 1020 output r6 as field.private;", 1021 ) 1022 .unwrap(); 1023 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1024 1025 // Declare the function name. 1026 let function_name = Identifier::from_str("compute").unwrap(); 1027 1028 // Initialize the RNG. 1029 let rng = &mut TestRng::default(); 1030 1031 // Construct the process. 1032 let process = crate::test_helpers::sample_process(&program); 1033 // Check that the circuit key can be synthesized. 1034 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 1035 1036 // Reset the process. 1037 let process = crate::test_helpers::sample_process(&program); 1038 1039 // Initialize a new caller account. 1040 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1041 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 1042 let caller = Address::try_from(&caller_private_key).unwrap(); 1043 1044 // Prepare a record belonging to the address. 1045 let record_string = format!("{{ owner: {caller}.private, token_amount: 100u64.private, _nonce: 0group.public }}"); 1046 1047 // Declare the input value. 1048 let r0 = Value::<CurrentNetwork>::from_str("3field").unwrap(); 1049 let r1 = Value::<CurrentNetwork>::from_str("5field").unwrap(); 1050 let r2 = Value::<CurrentNetwork>::from_str(&record_string).unwrap(); 1051 1052 // Authorize the function call. 1053 let authorization = process 1054 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [r0, r1, r2].iter(), rng) 1055 .unwrap(); 1056 assert_eq!(authorization.len(), 1); 1057 let request = authorization.peek_next().unwrap(); 1058 1059 // Compute the encryption randomizer as `HashToScalar(tvk || index)`. 1060 let randomizer = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(3)]).unwrap(); 1061 let nonce = CurrentNetwork::g_scalar_multiply(&randomizer); 1062 1063 // Declare the expected output value. 1064 let r3 = Value::<CurrentNetwork>::from_str(&format!( 1065 "{{ owner: {caller}.private, token_amount: 100u64.private, _nonce: {nonce}.public, _version: 1u8.public }}" 1066 )) 1067 .unwrap(); 1068 let r4 = Value::from_str("19field").unwrap(); 1069 let r5 = Value::from_str("11field").unwrap(); 1070 let r6 = Value::from_str("8field").unwrap(); 1071 1072 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 1073 assert_eq!(authorization.len(), 1); 1074 1075 // Compute the output value. 1076 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 1077 let candidate = response.outputs(); 1078 assert_eq!(4, candidate.len()); 1079 assert_eq!(r3, candidate[0]); 1080 assert_eq!(r4, candidate[1]); 1081 assert_eq!(r5, candidate[2]); 1082 assert_eq!(r6, candidate[3]); 1083 1084 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 1085 assert_eq!(authorization.len(), 1); 1086 1087 // Execute the request. 1088 let (response, _trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 1089 let candidate = response.outputs(); 1090 assert_eq!(4, candidate.len()); 1091 assert_eq!(r3, candidate[0]); 1092 assert_eq!(r4, candidate[1]); 1093 assert_eq!(r5, candidate[2]); 1094 assert_eq!(r6, candidate[3]); 1095 1096 // use circuit::Environment; 1097 // 1098 // assert_eq!(37080, CurrentAleo::num_constants()); 1099 // assert_eq!(12, CurrentAleo::num_public()); 1100 // assert_eq!(41630, CurrentAleo::num_private()); 1101 // assert_eq!(41685, CurrentAleo::num_constraints()); 1102 // assert_eq!(159387, CurrentAleo::num_gates()); 1103 } 1104 1105 #[test] 1106 fn test_process_execute_call_external_function() { 1107 // Initialize a new program. 1108 let (string, program0) = Program::<CurrentNetwork>::parse( 1109 r" 1110 program token.alpha; 1111 1112 record token: 1113 owner as address.private; 1114 amount as u64.private; 1115 1116 function mint: 1117 input r0 as address.private; 1118 input r1 as u64.private; 1119 cast r0 r1 into r2 as token.record; 1120 output r2 as token.record; 1121 1122 function produce_magic_number: 1123 add 1234u64 0u64 into r0; 1124 output r0 as u64.private; 1125 1126 function check_magic_number: 1127 input r0 as u64.private; 1128 assert.eq r0 1234u64; 1129 1130 function noop: 1131 1132 function transfer: 1133 input r0 as token.record; 1134 input r1 as address.private; 1135 input r2 as u64.private; 1136 sub r0.amount r2 into r3; 1137 cast r1 r2 into r4 as token.record; 1138 cast r0.owner r3 into r5 as token.record; 1139 output r4 as token.record; 1140 output r5 as token.record;", 1141 ) 1142 .unwrap(); 1143 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1144 1145 // Construct the process. 1146 let mut process = crate::test_helpers::sample_process(&program0); 1147 // Initialize another program. 1148 let (string, program1) = Program::<CurrentNetwork>::parse( 1149 r" 1150 import token.alpha; 1151 1152 program wallet.alpha; 1153 1154 function transfer: 1155 input r0 as token.alpha/token.record; 1156 input r1 as address.private; 1157 input r2 as u64.private; 1158 call token.alpha/noop; 1159 call token.alpha/produce_magic_number into r3; 1160 call token.alpha/check_magic_number r3; 1161 call token.alpha/transfer r0 r1 r2 into r4 r5; 1162 output r4 as token.alpha/token.record; 1163 output r5 as token.alpha/token.record;", 1164 ) 1165 .unwrap(); 1166 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1167 1168 // Add the program to the process. 1169 process.add_program(&program1).unwrap(); 1170 1171 // Initialize the RNG. 1172 let rng = &mut TestRng::default(); 1173 1174 // Initialize caller 0. 1175 let caller0_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1176 let caller0 = Address::try_from(&caller0_private_key).unwrap(); 1177 1178 // Initialize caller 1. 1179 let caller1_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1180 let caller1 = Address::try_from(&caller1_private_key).unwrap(); 1181 1182 // Declare the function name. 1183 let function_name = Identifier::from_str("transfer").unwrap(); 1184 1185 // Declare the input value. 1186 let r0 = Value::<CurrentNetwork>::from_str(&format!( 1187 "{{ owner: {caller0}.private, amount: 100u64.private, _nonce: 0group.public }}" 1188 )) 1189 .unwrap(); 1190 let r1 = Value::<CurrentNetwork>::from_str(&caller1.to_string()).unwrap(); 1191 let r2 = Value::<CurrentNetwork>::from_str("99u64").unwrap(); 1192 1193 // Authorize the function call. 1194 let authorization = process 1195 .authorize::<CurrentAleo, _>(&caller0_private_key, program1.id(), function_name, [r0, r1, r2].iter(), rng) 1196 .unwrap(); 1197 assert_eq!(authorization.len(), 5); 1198 println!("\nAuthorize\n{:#?}\n\n", authorization.to_vec_deque()); 1199 1200 let (output_a, output_b) = { 1201 // Fetch the first request. 1202 let request = authorization.to_vec_deque().pop_back().unwrap(); 1203 1204 // Compute the encryption randomizer as `HashToScalar(tvk || index)`. 1205 let randomizer_a = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(4)]).unwrap(); 1206 let nonce_a = CurrentNetwork::g_scalar_multiply(&randomizer_a); 1207 1208 // Compute the encryption randomizer as `HashToScalar(tvk || index)`. 1209 let randomizer_b = CurrentNetwork::hash_to_scalar_psd2(&[*request.tvk(), Field::from_u64(5)]).unwrap(); 1210 let nonce_b = CurrentNetwork::g_scalar_multiply(&randomizer_b); 1211 1212 // Declare the expected output value. 1213 let output_a = Value::from_str(&format!( 1214 "{{ owner: {caller1}.private, amount: 99u64.private, _nonce: {nonce_a}.public, _version: 1u8.public }}" 1215 )) 1216 .unwrap(); 1217 let output_b = Value::from_str(&format!( 1218 "{{ owner: {caller0}.private, amount: 1u64.private, _nonce: {nonce_b}.public, _version: 1u8.public }}" 1219 )) 1220 .unwrap(); 1221 1222 (output_a, output_b) 1223 }; 1224 1225 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 1226 assert_eq!(authorization.len(), 5); 1227 1228 // Compute the output value. 1229 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 1230 let candidate = response.outputs(); 1231 assert_eq!(2, candidate.len()); 1232 assert_eq!(output_a, candidate[0]); 1233 assert_eq!(output_b, candidate[1]); 1234 1235 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 1236 assert_eq!(authorization.len(), 5); 1237 1238 // Execute the request. 1239 let (response, _trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 1240 let candidate = response.outputs(); 1241 assert_eq!(2, candidate.len()); 1242 assert_eq!(output_a, candidate[0]); 1243 assert_eq!(output_b, candidate[1]); 1244 1245 // use circuit::Environment; 1246 // 1247 // assert_eq!(6427, CurrentAleo::num_constants()); 1248 // assert_eq!(8, CurrentAleo::num_public()); 1249 // assert_eq!(21264, CurrentAleo::num_private()); 1250 // assert_eq!(21279, CurrentAleo::num_constraints()); 1251 // assert_eq!(81872, CurrentAleo::num_gates()); 1252 // 1253 // assert_eq!(18504, CurrentAleo::num_constants()); 1254 // assert_eq!(17, CurrentAleo::num_public()); 1255 // assert_eq!(58791, CurrentAleo::num_private()); 1256 // assert_eq!(58855, CurrentAleo::num_constraints()); 1257 // assert_eq!(215810, CurrentAleo::num_gates()); 1258 } 1259 1260 #[test] 1261 fn test_process_execute_and_finalize_get_add_set() { 1262 // Initialize a new program. 1263 let (string, program) = Program::<CurrentNetwork>::parse( 1264 r" 1265 program testing.alpha; 1266 1267 mapping account: 1268 key as address.public; 1269 value as u64.public; 1270 1271 function compute: 1272 input r0 as address.public; 1273 input r1 as u64.public; 1274 input r2 as u64.public; 1275 add r1 r2 into r3; 1276 async compute r0 r3 into r4; 1277 output r4 as testing.alpha/compute.future; 1278 1279 finalize compute: 1280 input r0 as address.public; 1281 input r1 as u64.public; 1282 get.or_use account[r0] 0u64 into r2; 1283 add r2 r1 into r3; 1284 set r3 into account[r0]; 1285 ", 1286 ) 1287 .unwrap(); 1288 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1289 1290 // Declare the program ID. 1291 let program_id = program.id(); 1292 // Declare the mapping. 1293 let mapping_name = Identifier::from_str("account").unwrap(); 1294 // Declare the function name. 1295 let function_name = Identifier::from_str("compute").unwrap(); 1296 1297 // Initialize the RNG. 1298 let rng = &mut TestRng::default(); 1299 1300 // Construct the process. 1301 let process = crate::test_helpers::sample_process(&program); 1302 // Check that the circuit key can be synthesized. 1303 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 1304 1305 // Reset the process. 1306 let mut process = Process::load().unwrap(); 1307 1308 // Initialize a new block store. 1309 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1310 // Initialize a new finalize store. 1311 let finalize_store = FinalizeStore::<_, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1312 1313 // Add the program to the process. 1314 let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 1315 // Check that the deployment verifies. 1316 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 1317 // Compute the fee. 1318 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 1319 // Finalize the deployment. 1320 let (stack, _) = process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap(); 1321 // Add the stack *manually* to the process. 1322 process.add_stack(stack); 1323 1324 // Initialize a new caller account. 1325 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1326 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 1327 let caller = Address::try_from(&caller_private_key).unwrap(); 1328 1329 // Declare the input value. 1330 let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap(); 1331 let r1 = Value::<CurrentNetwork>::from_str("3u64").unwrap(); 1332 let r2 = Value::<CurrentNetwork>::from_str("5u64").unwrap(); 1333 1334 // Authorize the function call. 1335 let authorization = process 1336 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [r0, r1, r2].iter(), rng) 1337 .unwrap(); 1338 assert_eq!(authorization.len(), 1); 1339 1340 let expected_execution_cost = 1341 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 1342 1343 // Compute the output value. 1344 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 1345 let candidate = response.outputs(); 1346 assert_eq!(1, candidate.len()); 1347 1348 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 1349 assert_eq!(authorization.len(), 1); 1350 1351 // Execute the request. 1352 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 1353 let candidate = response.outputs(); 1354 assert_eq!(1, candidate.len()); 1355 1356 // Prepare the trace. 1357 trace.prepare(&Query::from(block_store)).unwrap(); 1358 // Prove the execution. 1359 let execution = trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V2, rng).unwrap(); 1360 // Verify the execution. 1361 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 1362 1363 // Check the execution cost 1364 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 1365 1366 // Now, finalize the execution. 1367 process.finalize_execution(sample_finalize_state(1), &finalize_store, &execution, None).unwrap(); 1368 1369 // Check that the account balance is now 8. 1370 let candidate = finalize_store 1371 .get_value_speculative(*program_id, mapping_name, &Plaintext::from(Literal::Address(caller))) 1372 .unwrap() 1373 .unwrap(); 1374 assert_eq!(candidate, Value::from_str("8u64").unwrap()); 1375 } 1376 1377 #[test] 1378 fn test_process_execute_and_finalize_increment_decrement_via_get_set() { 1379 // Initialize a new program. 1380 let (string, program) = Program::<CurrentNetwork>::parse( 1381 r" 1382 program testing.alpha; 1383 1384 mapping account: 1385 key as address.public; 1386 value as u64.public; 1387 1388 function compute: 1389 input r0 as address.public; 1390 input r1 as u64.public; 1391 input r2 as u64.public; 1392 add r1 r2 into r3; 1393 async compute r0 r3 into r4; 1394 output r4 as testing.alpha/compute.future; 1395 1396 finalize compute: 1397 input r0 as address.public; 1398 input r1 as u64.public; 1399 get.or_use account[r0] 0u64 into r2; 1400 add r2 r1 into r3; 1401 sub r3 r1 into r4; 1402 set r4 into account[r0]; 1403 ", 1404 ) 1405 .unwrap(); 1406 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1407 1408 // Declare the program ID. 1409 let program_id = program.id(); 1410 // Declare the mapping. 1411 let mapping_name = Identifier::from_str("account").unwrap(); 1412 // Declare the function name. 1413 let function_name = Identifier::from_str("compute").unwrap(); 1414 1415 // Initialize the RNG. 1416 let rng = &mut TestRng::default(); 1417 1418 // Construct the process. 1419 let process = crate::test_helpers::sample_process(&program); 1420 // Check that the circuit key can be synthesized. 1421 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 1422 1423 // Reset the process. 1424 let mut process = Process::load().unwrap(); 1425 1426 // Initialize a new block store. 1427 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1428 // Initialize a new finalize store. 1429 let finalize_store = FinalizeStore::<_, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1430 1431 // Add the program to the process. 1432 let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 1433 // Check that the deployment verifies. 1434 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 1435 // Compute the fee. 1436 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 1437 // Finalize the deployment. 1438 let (stack, _) = process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap(); 1439 // Add the stack *manually* to the process. 1440 process.add_stack(stack); 1441 1442 // Initialize a new caller account. 1443 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1444 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 1445 let caller = Address::try_from(&caller_private_key).unwrap(); 1446 1447 // Declare the input value. 1448 let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap(); 1449 let r1 = Value::<CurrentNetwork>::from_str("3u64").unwrap(); 1450 let r2 = Value::<CurrentNetwork>::from_str("5u64").unwrap(); 1451 1452 // Authorize the function call. 1453 let authorization = process 1454 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [r0, r1, r2].iter(), rng) 1455 .unwrap(); 1456 assert_eq!(authorization.len(), 1); 1457 1458 let expected_execution_cost = 1459 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 1460 1461 // Compute the output value. 1462 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 1463 let candidate = response.outputs(); 1464 assert_eq!(1, candidate.len()); 1465 1466 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 1467 assert_eq!(authorization.len(), 1); 1468 1469 // Execute the request. 1470 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 1471 let candidate = response.outputs(); 1472 assert_eq!(1, candidate.len()); 1473 1474 // Prepare the trace. 1475 trace.prepare(&Query::from(block_store)).unwrap(); 1476 // Prove the execution. 1477 let execution = trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V2, rng).unwrap(); 1478 1479 // Verify the execution. 1480 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 1481 1482 // Check the execution cost 1483 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 1484 1485 // Now, finalize the execution. 1486 process.finalize_execution(sample_finalize_state(1), &finalize_store, &execution, None).unwrap(); 1487 1488 // Check that the account balance is now 0. 1489 let candidate = finalize_store 1490 .get_value_speculative(*program_id, mapping_name, &Plaintext::from(Literal::Address(caller))) 1491 .unwrap() 1492 .unwrap(); 1493 assert_eq!(candidate, Value::from_str("0u64").unwrap()); 1494 } 1495 1496 #[test] 1497 fn test_process_execute_mint_public() { 1498 // Initialize a new program. 1499 let (string, program) = Program::<CurrentNetwork>::parse( 1500 r" 1501 program token.alpha; 1502 1503 // On-chain storage of an `account` map, with `owner` as the key, 1504 // and `amount` as the value. 1505 mapping account: 1506 // The token owner. 1507 key as address.public; 1508 // The token amount. 1509 value as u64.public; 1510 1511 // The function `mint_public` issues the specified token amount 1512 // for the token receiver publicly on the network. 1513 function mint_public: 1514 // Input the token receiver. 1515 input r0 as address.public; 1516 // Input the token amount. 1517 input r1 as u64.public; 1518 // Mint the tokens publicly. 1519 async mint_public r0 r1 into r2; 1520 output r2 as token.alpha/mint_public.future; 1521 1522 // The finalize scope of `mint_public` increments the 1523 // `account` of the token receiver by the specified amount. 1524 finalize mint_public: 1525 // Input the token receiver. 1526 input r0 as address.public; 1527 // Input the token amount. 1528 input r1 as u64.public; 1529 1530 // Get `account[r0]` into `r2`, defaulting to 0u64 if the entry does not exist. 1531 get.or_use account[r0] 0u64 into r2; 1532 // Add `r1` to `r2`. If the operation overflows, `mint_public` is reverted. 1533 add r2 r1 into r3; 1534 // Set `r3` into `account[r0]`. 1535 set r3 into account[r0]; 1536 ", 1537 ) 1538 .unwrap(); 1539 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1540 1541 // Declare the program ID. 1542 let program_id = program.id(); 1543 // Declare the mapping. 1544 let mapping_name = Identifier::from_str("account").unwrap(); 1545 // Declare the function name. 1546 let function_name = Identifier::from_str("mint_public").unwrap(); 1547 1548 // Initialize the RNG. 1549 let rng = &mut TestRng::default(); 1550 1551 // Construct the process. 1552 let process = crate::test_helpers::sample_process(&program); 1553 // Check that the circuit key can be synthesized. 1554 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 1555 1556 // Reset the process. 1557 let mut process = Process::load().unwrap(); 1558 1559 // Initialize a new block store. 1560 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1561 // Initialize a new finalize store. 1562 let finalize_store = FinalizeStore::<_, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1563 1564 // Add the program to the process. 1565 let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 1566 // Check that the deployment verifies. 1567 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 1568 // Compute the fee. 1569 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 1570 // Finalize the deployment. 1571 let (stack, _) = process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap(); 1572 // Add the stack *manually* to the process. 1573 process.add_stack(stack); 1574 1575 // TODO (howardwu): Remove this. I call this to synthesize the proving key independent of the assignment from 'execute'. 1576 // In general, we should update all tests to utilize a presynthesized proving key, before execution, to test 1577 // the correctness of the synthesizer. 1578 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 1579 1580 // Initialize a new caller account. 1581 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1582 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 1583 let caller = Address::try_from(&caller_private_key).unwrap(); 1584 1585 // Declare the input value. 1586 let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap(); 1587 let r1 = Value::<CurrentNetwork>::from_str("3u64").unwrap(); 1588 1589 // Authorize the function call. 1590 let authorization = process 1591 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [r0, r1].iter(), rng) 1592 .unwrap(); 1593 assert_eq!(authorization.len(), 1); 1594 1595 // Compute the output value. 1596 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 1597 let candidate = response.outputs(); 1598 assert_eq!(1, candidate.len()); 1599 1600 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 1601 assert_eq!(authorization.len(), 1); 1602 1603 let expected_execution_cost = 1604 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 1605 1606 // Execute the request. 1607 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 1608 let candidate = response.outputs(); 1609 assert_eq!(1, candidate.len()); 1610 1611 // Prepare the trace. 1612 trace.prepare(&Query::from(block_store)).unwrap(); 1613 // Prove the execution. 1614 let execution = trace.prove_execution::<CurrentAleo, _>("token", VarunaVersion::V2, rng).unwrap(); 1615 1616 // Verify the execution. 1617 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 1618 1619 // Check the execution cost 1620 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 1621 1622 // Now, finalize the execution. 1623 process.finalize_execution(sample_finalize_state(1), &finalize_store, &execution, None).unwrap(); 1624 1625 // Check the account balance. 1626 let candidate = finalize_store 1627 .get_value_speculative(*program_id, mapping_name, &Plaintext::from(Literal::Address(caller))) 1628 .unwrap() 1629 .unwrap(); 1630 assert_eq!(candidate, Value::from_str("3u64").unwrap()); 1631 } 1632 1633 #[test] 1634 fn test_process_execute_call_mint_public() { 1635 // Initialize a new program. 1636 let (string, program0) = Program::<CurrentNetwork>::parse( 1637 r" 1638 program token.alpha; 1639 1640 // On-chain storage of an `account` map, with `owner` as the key, 1641 // and `amount` as the value. 1642 mapping account: 1643 // The token owner. 1644 key as address.public; 1645 // The token amount. 1646 value as u64.public; 1647 1648 // The function `mint_public` issues the specified token amount 1649 // for the token receiver publicly on the network. 1650 function mint_public: 1651 // Input the token receiver. 1652 input r0 as address.public; 1653 // Input the token amount. 1654 input r1 as u64.public; 1655 // Mint the tokens publicly. 1656 async mint_public r0 r1 into r2; 1657 output r2 as token.alpha/mint_public.future; 1658 1659 // The finalize scope of `mint_public` increments the 1660 // `account` of the token receiver by the specified amount. 1661 finalize mint_public: 1662 // Input the token receiver. 1663 input r0 as address.public; 1664 // Input the token amount. 1665 input r1 as u64.public; 1666 1667 // Get `account[r0]` into `r2`, defaulting to 0u64 if the entry does not exist. 1668 get.or_use account[r0] 0u64 into r2; 1669 // Add `r1` to `r2`. If the operation overflows, `mint_public` is reverted. 1670 add r2 r1 into r3; 1671 // Set `r3` into `account[r0]`. 1672 set r3 into account[r0]; 1673 ", 1674 ) 1675 .unwrap(); 1676 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1677 1678 // Declare the mapping. 1679 let mapping_name = Identifier::from_str("account").unwrap(); 1680 // Declare the function name. 1681 let function_name = Identifier::from_str("mint_public").unwrap(); 1682 1683 // Initialize the RNG. 1684 let rng = &mut TestRng::default(); 1685 1686 // Construct the process. 1687 let process = crate::test_helpers::sample_process(&program0); 1688 // Check that the circuit key can be synthesized. 1689 process.synthesize_key::<CurrentAleo, _>(program0.id(), &function_name, rng).unwrap(); 1690 1691 // Reset the process. 1692 let mut process = Process::load().unwrap(); 1693 1694 // Initialize a new block store. 1695 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1696 // Initialize a new finalize store. 1697 let finalize_store = FinalizeStore::<_, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1698 1699 // Add the program to the process. 1700 let deployment = process.deploy::<CurrentAleo, _>(&program0, rng).unwrap(); 1701 // Check that the deployment verifies. 1702 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 1703 // Compute the fee. 1704 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 1705 // Finalize the deployment. 1706 let (stack, _) = process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap(); 1707 // Add the stack *manually* to the process. 1708 process.add_stack(stack); 1709 1710 // TODO (howardwu): Remove this. I call this to synthesize the proving key independent of the assignment from 'execute'. 1711 // In general, we should update all tests to utilize a presynthesized proving key, before execution, to test 1712 // the correctness of the synthesizer. 1713 process.synthesize_key::<CurrentAleo, _>(program0.id(), &function_name, rng).unwrap(); 1714 1715 // Initialize another program. 1716 let (string, program1) = Program::<CurrentNetwork>::parse( 1717 r" 1718 import token.alpha; 1719 1720 program public_wallet.alpha; 1721 1722 function init: 1723 input r0 as address.public; 1724 input r1 as u64.public; 1725 call token.alpha/mint_public r0 r1 into r2; 1726 async init r2 into r3; 1727 output r3 as public_wallet.alpha/init.future; 1728 finalize init: 1729 input r0 as token.alpha/mint_public.future; 1730 await r0; 1731 ", 1732 ) 1733 .unwrap(); 1734 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1735 1736 // Declare the function name. 1737 let function_name = Identifier::from_str("init").unwrap(); 1738 1739 // Add the program to the process. 1740 let deployment = process.deploy::<CurrentAleo, _>(&program1, rng).unwrap(); 1741 // Check that the deployment verifies. 1742 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 1743 // Compute the fee. 1744 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 1745 // Finalize the deployment. 1746 let (stack, _) = process.finalize_deployment(sample_finalize_state(2), &finalize_store, &deployment, &fee).unwrap(); 1747 // Add the stack *manually* to the process. 1748 process.add_stack(stack); 1749 1750 // TODO (howardwu): Remove this. I call this to synthesize the proving key independent of the assignment from 'execute'. 1751 // In general, we should update all tests to utilize a presynthesized proving key, before execution, to test 1752 // the correctness of the synthesizer. 1753 process.synthesize_key::<CurrentAleo, _>(program1.id(), &function_name, rng).unwrap(); 1754 1755 // Initialize caller. 1756 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1757 let caller = Address::try_from(&caller_private_key).unwrap(); 1758 1759 // Declare the input value. 1760 let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap(); 1761 let r1 = Value::<CurrentNetwork>::from_str("100u64").unwrap(); 1762 1763 // Authorize the function call. 1764 let authorization = process 1765 .authorize::<CurrentAleo, _>(&caller_private_key, program1.id(), function_name, [r0, r1].iter(), rng) 1766 .unwrap(); 1767 assert_eq!(authorization.len(), 2); 1768 1769 let expected_execution_cost = 1770 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 1771 1772 // Compute the output value. 1773 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 1774 let candidate = response.outputs(); 1775 assert_eq!(1, candidate.len()); 1776 1777 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 1778 assert_eq!(authorization.len(), 2); 1779 1780 // Execute the request. 1781 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 1782 let candidate = response.outputs(); 1783 assert_eq!(1, candidate.len()); 1784 1785 // Prepare the trace. 1786 trace.prepare(&Query::from(block_store)).unwrap(); 1787 // Prove the execution. 1788 let execution = trace.prove_execution::<CurrentAleo, _>("public_wallet", VarunaVersion::V2, rng).unwrap(); 1789 1790 // Verify the execution. 1791 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 1792 1793 // Check the execution cost 1794 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 1795 1796 // Now, finalize the execution. 1797 process.finalize_execution(sample_finalize_state(1), &finalize_store, &execution, None).unwrap(); 1798 1799 // Check the account balance. 1800 let candidate = finalize_store 1801 .get_value_speculative(*program0.id(), mapping_name, &Plaintext::from(Literal::Address(caller))) 1802 .unwrap() 1803 .unwrap(); 1804 assert_eq!(candidate, Value::from_str("100u64").unwrap()); 1805 } 1806 1807 #[test] 1808 fn test_process_execute_and_finalize_get_set() { 1809 // Initialize a new program. 1810 let (string, program) = Program::<CurrentNetwork>::parse( 1811 r" 1812 program testing.alpha; 1813 1814 mapping account: 1815 key as address.public; 1816 value as u64.public; 1817 1818 function compute: 1819 input r0 as address.public; 1820 input r1 as u64.public; 1821 input r2 as u64.public; 1822 add r1 r2 into r3; 1823 async compute r0 r3 into r4; 1824 output r4 as testing.alpha/compute.future; 1825 1826 finalize compute: 1827 input r0 as address.public; 1828 input r1 as u64.public; 1829 get.or_use account[r0] 0u64 into r2; 1830 add r1 r2 into r3; 1831 set r3 into account[r0]; 1832 get account[r0] into r4; 1833 add r1 r4 into r5; 1834 set r5 into account[r0]; 1835 ", 1836 ) 1837 .unwrap(); 1838 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1839 1840 // Declare the program ID. 1841 let program_id = program.id(); 1842 // Declare the mapping. 1843 let mapping_name = Identifier::from_str("account").unwrap(); 1844 // Declare the function name. 1845 let function_name = Identifier::from_str("compute").unwrap(); 1846 1847 // Initialize the RNG. 1848 let rng = &mut TestRng::default(); 1849 1850 // Construct the process. 1851 let process = crate::test_helpers::sample_process(&program); 1852 // Check that the circuit key can be synthesized. 1853 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 1854 1855 // Reset the process. 1856 let mut process = Process::load().unwrap(); 1857 1858 // Initialize a new block store. 1859 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1860 // Initialize a new finalize store. 1861 let finalize_store = FinalizeStore::<_, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 1862 1863 // Add the program to the process. 1864 let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 1865 // Check that the deployment verifies. 1866 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 1867 // Compute the fee. 1868 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 1869 // Finalize the deployment. 1870 let (stack, _) = process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap(); 1871 // Add the stack *manually* to the process. 1872 process.add_stack(stack); 1873 1874 // Initialize a new caller account. 1875 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1876 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 1877 let caller = Address::try_from(&caller_private_key).unwrap(); 1878 1879 // Declare the input value. 1880 let r0 = Value::<CurrentNetwork>::from_str(&caller.to_string()).unwrap(); 1881 let r1 = Value::<CurrentNetwork>::from_str("3u64").unwrap(); 1882 let r2 = Value::<CurrentNetwork>::from_str("5u64").unwrap(); 1883 1884 // Authorize the function call. 1885 let authorization = process 1886 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [r0, r1, r2].iter(), rng) 1887 .unwrap(); 1888 assert_eq!(authorization.len(), 1); 1889 1890 // Compute the output value. 1891 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 1892 let candidate = response.outputs(); 1893 assert_eq!(1, candidate.len()); 1894 1895 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 1896 assert_eq!(authorization.len(), 1); 1897 1898 let expected_execution_cost = 1899 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 1900 1901 // Execute the request. 1902 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 1903 let candidate = response.outputs(); 1904 assert_eq!(1, candidate.len()); 1905 1906 // Prepare the trace. 1907 trace.prepare(&Query::from(block_store)).unwrap(); 1908 // Prove the execution. 1909 let execution = trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V2, rng).unwrap(); 1910 1911 // Verify the execution. 1912 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 1913 1914 // Check the execution cost 1915 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 1916 1917 // Now, finalize the execution. 1918 process.finalize_execution(sample_finalize_state(1), &finalize_store, &execution, None).unwrap(); 1919 1920 // Check that the account balance is now 8. 1921 let candidate = finalize_store 1922 .get_value_speculative(*program_id, mapping_name, &Plaintext::from(Literal::Address(caller))) 1923 .unwrap() 1924 .unwrap(); 1925 assert_eq!(candidate, Value::from_str("16u64").unwrap()); 1926 } 1927 1928 #[test] 1929 fn test_execution_order() { 1930 // Initialize a new program. 1931 let (string, program0) = Program::<CurrentNetwork>::parse( 1932 r" 1933 program zero.alpha; 1934 1935 function c: 1936 input r0 as u8.private; 1937 input r1 as u8.private; 1938 add r0 r1 into r2; 1939 output r2 as u8.private;", 1940 ) 1941 .unwrap(); 1942 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1943 1944 // Construct the process. 1945 let mut process = crate::test_helpers::sample_process(&program0); 1946 1947 // Initialize another program. 1948 let (string, program1) = Program::<CurrentNetwork>::parse( 1949 r" 1950 import zero.alpha; 1951 1952 program one.alpha; 1953 1954 function b: 1955 input r0 as u8.private; 1956 input r1 as u8.private; 1957 call zero.alpha/c r0 r1 into r2; 1958 output r2 as u8.private;", 1959 ) 1960 .unwrap(); 1961 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1962 1963 // Add the program to the process. 1964 process.add_program(&program1).unwrap(); 1965 1966 // Initialize another program. 1967 let (string, program2) = Program::<CurrentNetwork>::parse( 1968 r" 1969 import one.alpha; 1970 1971 program two.alpha; 1972 1973 function a: 1974 input r0 as u8.private; 1975 input r1 as u8.private; 1976 call one.alpha/b r0 r1 into r2; 1977 output r2 as u8.private;", 1978 ) 1979 .unwrap(); 1980 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 1981 1982 // Add the program to the process. 1983 process.add_program(&program2).unwrap(); 1984 1985 // Initialize the RNG. 1986 let rng = &mut TestRng::default(); 1987 1988 // Initialize the caller. 1989 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 1990 1991 // Declare the function name. 1992 let function_name = Identifier::from_str("a").unwrap(); 1993 1994 // Declare the input value. 1995 let r0 = Value::<CurrentNetwork>::from_str("1u8").unwrap(); 1996 let r1 = Value::<CurrentNetwork>::from_str("2u8").unwrap(); 1997 1998 // Authorize the function call. 1999 let authorization = process 2000 .authorize::<CurrentAleo, _>(&caller_private_key, program2.id(), function_name, [r0, r1].iter(), rng) 2001 .unwrap(); 2002 assert_eq!(authorization.len(), 3); 2003 println!("\nAuthorize\n{:#?}\n\n", authorization.to_vec_deque()); 2004 2005 let output = Value::<CurrentNetwork>::from_str("3u8").unwrap(); 2006 2007 // Compute the output value. 2008 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 2009 let candidate = response.outputs(); 2010 assert_eq!(1, candidate.len()); 2011 assert_eq!(output, candidate[0]); 2012 2013 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 2014 assert_eq!(authorization.len(), 3); 2015 2016 let expected_execution_cost = 2017 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 2018 2019 // Execute the request. 2020 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 2021 let candidate = response.outputs(); 2022 assert_eq!(1, candidate.len()); 2023 assert_eq!(output, candidate[0]); 2024 2025 // Construct the expected transition order. 2026 let expected_order = [ 2027 (program0.id(), Identifier::<MainnetV0>::from_str("c").unwrap()), 2028 (program1.id(), Identifier::from_str("b").unwrap()), 2029 (program2.id(), Identifier::from_str("a").unwrap()), 2030 ]; 2031 2032 // Check the expected transition order. 2033 for (transition, (expected_program_id, expected_function_name)) in 2034 trace.transitions().iter().zip_eq(expected_order.iter()) 2035 { 2036 assert_eq!(transition.program_id(), *expected_program_id); 2037 assert_eq!(transition.function_name(), expected_function_name); 2038 } 2039 2040 // Initialize a new block store. 2041 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 2042 // Prepare the trace. 2043 trace.prepare(&Query::from(block_store)).unwrap(); 2044 // Prove the execution. 2045 let execution = trace.prove_execution::<CurrentAleo, _>("two", VarunaVersion::V2, rng).unwrap(); 2046 2047 // Verify the execution. 2048 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 2049 2050 // Check the execution cost 2051 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 2052 } 2053 2054 #[test] 2055 fn test_complex_execution_order() { 2056 // This test checks that the execution order is correct. 2057 // The functions are invoked in the following order: 2058 // "four::a" 2059 // --> "two::b" 2060 // --> "zero::c" 2061 // --> "one::d" 2062 // --> "three::e" 2063 // --> "two::b" 2064 // --> "zero::c" 2065 // --> "one::d" 2066 // --> "one::d" 2067 // --> "zero::c" 2068 // The linearized order is: 2069 // - [a, b, c, d, e, b, c, d, d, c] 2070 // The transitions must be included in the `Execution` in the order they finish. 2071 // The execution order is: 2072 // - [c, d, b, c, d, b, d, c, e, a] 2073 2074 // Initialize a new program. 2075 let (string, program0) = Program::<CurrentNetwork>::parse( 2076 r" 2077 program zero.alpha; 2078 2079 function c: 2080 input r0 as u8.private; 2081 input r1 as u8.private; 2082 add r0 r1 into r2; 2083 output r2 as u8.private;", 2084 ) 2085 .unwrap(); 2086 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 2087 2088 // Construct the process. 2089 let mut process = crate::test_helpers::sample_process(&program0); 2090 2091 // Initialize another program. 2092 let (string, program1) = Program::<CurrentNetwork>::parse( 2093 r" 2094 program one.alpha; 2095 2096 function d: 2097 input r0 as u8.private; 2098 input r1 as u8.private; 2099 add r0 r1 into r2; 2100 output r2 as u8.private;", 2101 ) 2102 .unwrap(); 2103 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 2104 2105 // Add the program to the process. 2106 process.add_program(&program1).unwrap(); 2107 2108 // Initialize another program. 2109 let (string, program2) = Program::<CurrentNetwork>::parse( 2110 r" 2111 import zero.alpha; 2112 import one.alpha; 2113 2114 program two.alpha; 2115 2116 function b: 2117 input r0 as u8.private; 2118 input r1 as u8.private; 2119 call zero.alpha/c r0 r1 into r2; 2120 call one.alpha/d r1 r2 into r3; 2121 output r3 as u8.private;", 2122 ) 2123 .unwrap(); 2124 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 2125 2126 // Add the program to the process. 2127 process.add_program(&program2).unwrap(); 2128 2129 // Initialize another program. 2130 let (string, program3) = Program::<CurrentNetwork>::parse( 2131 r" 2132 import zero.alpha; 2133 import one.alpha; 2134 import two.alpha; 2135 2136 program three.alpha; 2137 2138 function e: 2139 input r0 as u8.private; 2140 input r1 as u8.private; 2141 call two.alpha/b r0 r1 into r2; 2142 call one.alpha/d r1 r2 into r3; 2143 call zero.alpha/c r1 r2 into r4; 2144 output r4 as u8.private;", 2145 ) 2146 .unwrap(); 2147 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 2148 2149 // Add the program to the process. 2150 process.add_program(&program3).unwrap(); 2151 2152 // Initialize another program. 2153 let (string, program4) = Program::<CurrentNetwork>::parse( 2154 r" 2155 import two.alpha; 2156 import three.alpha; 2157 2158 program four.alpha; 2159 2160 function a: 2161 input r0 as u8.private; 2162 input r1 as u8.private; 2163 call two.alpha/b r0 r1 into r2; 2164 call three.alpha/e r1 r2 into r3; 2165 output r3 as u8.private;", 2166 ) 2167 .unwrap(); 2168 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 2169 2170 // Add the program to the process. 2171 process.add_program(&program4).unwrap(); 2172 2173 // Initialize the RNG. 2174 let rng = &mut TestRng::default(); 2175 2176 // Initialize caller. 2177 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 2178 2179 // Declare the function name. 2180 let function_name = Identifier::from_str("a").unwrap(); 2181 2182 // Declare the input value. 2183 let r0 = Value::<CurrentNetwork>::from_str("1u8").unwrap(); 2184 let r1 = Value::<CurrentNetwork>::from_str("2u8").unwrap(); 2185 2186 // Authorize the function call. 2187 let authorization = process 2188 .authorize::<CurrentAleo, _>(&caller_private_key, program4.id(), function_name, [r0, r1].iter(), rng) 2189 .unwrap(); 2190 assert_eq!(authorization.len(), 10); 2191 println!("\nAuthorize\n{:#?}\n\n", authorization.to_vec_deque()); 2192 2193 let expected_execution_cost = 2194 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 2195 2196 let output = Value::<CurrentNetwork>::from_str("17u8").unwrap(); 2197 2198 // Compute the output value. 2199 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 2200 let candidate = response.outputs(); 2201 assert_eq!(1, candidate.len()); 2202 assert_eq!(output, candidate[0]); 2203 2204 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 2205 assert_eq!(authorization.len(), 10); 2206 2207 // Execute the request. 2208 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 2209 let candidate = response.outputs(); 2210 assert_eq!(1, candidate.len()); 2211 assert_eq!(output, candidate[0]); 2212 2213 // Construct the expected execution order. 2214 let expected_order = [ 2215 (program0.id(), Identifier::<MainnetV0>::from_str("c").unwrap()), 2216 (program1.id(), Identifier::<MainnetV0>::from_str("d").unwrap()), 2217 (program2.id(), Identifier::<MainnetV0>::from_str("b").unwrap()), 2218 (program0.id(), Identifier::<MainnetV0>::from_str("c").unwrap()), 2219 (program1.id(), Identifier::<MainnetV0>::from_str("d").unwrap()), 2220 (program2.id(), Identifier::<MainnetV0>::from_str("b").unwrap()), 2221 (program1.id(), Identifier::<MainnetV0>::from_str("d").unwrap()), 2222 (program0.id(), Identifier::<MainnetV0>::from_str("c").unwrap()), 2223 (program3.id(), Identifier::<MainnetV0>::from_str("e").unwrap()), 2224 (program4.id(), Identifier::<MainnetV0>::from_str("a").unwrap()), 2225 ]; 2226 for (transition, (expected_program_id, expected_function_name)) in 2227 trace.transitions().iter().zip_eq(expected_order.iter()) 2228 { 2229 assert_eq!(transition.program_id(), *expected_program_id); 2230 assert_eq!(transition.function_name(), expected_function_name); 2231 } 2232 2233 // Initialize a new block store. 2234 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 2235 // Prepare the trace. 2236 trace.prepare(&Query::from(block_store)).unwrap(); 2237 // Prove the execution. 2238 let execution = trace.prove_execution::<CurrentAleo, _>("four", VarunaVersion::V2, rng).unwrap(); 2239 2240 // Verify the execution. 2241 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 2242 2243 // Check the execution cost 2244 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 2245 } 2246 2247 #[test] 2248 fn test_process_execute_and_finalize_get_set_with_struct() { 2249 // Initialize a new program. 2250 let (string, program) = Program::<CurrentNetwork>::parse( 2251 r" 2252 program testing.alpha; 2253 2254 struct entry: 2255 count as u8; 2256 data as u8; 2257 2258 mapping entries: 2259 key as address.public; 2260 value as entry.public; 2261 2262 function compute: 2263 input r0 as u8.public; 2264 input r1 as u8.public; 2265 cast r0 r1 into r2 as entry; 2266 async compute self.caller r2 into r3; 2267 output r3 as testing.alpha/compute.future; 2268 2269 finalize compute: 2270 input r0 as address.public; 2271 input r1 as entry.public; 2272 get.or_use entries[r0] r1 into r2; 2273 add r1.count r2.count into r3; 2274 add r1.data r2.data into r4; 2275 cast r3 r4 into r5 as entry; 2276 set r5 into entries[r0]; 2277 get entries[r0] into r6; 2278 add r6.count r1.count into r7; 2279 add r6.data r1.data into r8; 2280 cast r7 r8 into r9 as entry; 2281 set r9 into entries[r0]; 2282 ", 2283 ) 2284 .unwrap(); 2285 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 2286 2287 // Declare the program ID. 2288 let program_id = program.id(); 2289 // Declare the mapping. 2290 let mapping_name = Identifier::from_str("entries").unwrap(); 2291 // Declare the function name. 2292 let function_name = Identifier::from_str("compute").unwrap(); 2293 2294 // Initialize the RNG. 2295 let rng = &mut TestRng::default(); 2296 2297 // Construct the process. 2298 let process = crate::test_helpers::sample_process(&program); 2299 // Check that the circuit key can be synthesized. 2300 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 2301 2302 // Reset the process. 2303 let mut process = Process::load().unwrap(); 2304 2305 // Initialize a new block store. 2306 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 2307 // Initialize a new finalize store. 2308 let finalize_store = FinalizeStore::<_, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 2309 2310 // Add the program to the process. 2311 let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 2312 // Check that the deployment verifies. 2313 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 2314 // Compute the fee. 2315 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 2316 // Finalize the deployment. 2317 let (stack, _) = process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap(); 2318 // Add the stack *manually* to the process. 2319 process.add_stack(stack); 2320 2321 // Initialize a new caller account. 2322 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 2323 let _caller_view_key = ViewKey::try_from(&caller_private_key).unwrap(); 2324 let caller = Address::try_from(&caller_private_key).unwrap(); 2325 2326 // Declare the input value. 2327 let r0 = Value::<CurrentNetwork>::from_str("1u8").unwrap(); 2328 let r1 = Value::<CurrentNetwork>::from_str("2u8").unwrap(); 2329 2330 // Authorize the function call. 2331 let authorization = process 2332 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [r0, r1].iter(), rng) 2333 .unwrap(); 2334 assert_eq!(authorization.len(), 1); 2335 2336 // Compute the output value. 2337 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 2338 let candidate = response.outputs(); 2339 assert_eq!(1, candidate.len()); 2340 2341 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 2342 assert_eq!(authorization.len(), 1); 2343 2344 let expected_execution_cost = 2345 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 2346 2347 // Execute the request. 2348 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 2349 let candidate = response.outputs(); 2350 assert_eq!(1, candidate.len()); 2351 2352 // Prepare the trace. 2353 trace.prepare(&Query::from(block_store)).unwrap(); 2354 // Prove the execution. 2355 let execution = trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V2, rng).unwrap(); 2356 2357 // Verify the execution. 2358 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 2359 2360 // Check the execution cost 2361 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 2362 2363 // Now, finalize the execution. 2364 process.finalize_execution(sample_finalize_state(1), &finalize_store, &execution, None).unwrap(); 2365 2366 // Check that the struct is stored as expected. 2367 let candidate = finalize_store 2368 .get_value_speculative(*program_id, mapping_name, &Plaintext::from(Literal::Address(caller))) 2369 .unwrap() 2370 .unwrap(); 2371 assert_eq!(candidate, Value::from_str("{ count: 3u8, data: 6u8 }").unwrap()); 2372 } 2373 2374 #[test] 2375 fn test_process_execute_and_verify_call_to_closure() { 2376 // Initialize a new program. 2377 let (string, program) = Program::<CurrentNetwork>::parse( 2378 r" 2379 program testing.alpha; 2380 2381 // (a + (a + b)) + (a + b) == (3a + 2b) 2382 closure execute: 2383 input r0 as field; 2384 input r1 as field; 2385 add r0 r1 into r2; 2386 add r0 r2 into r3; 2387 add r2 r3 into r4; 2388 output r4 as field; 2389 output r3 as field; 2390 output r2 as field; 2391 2392 closure check_not_equal: 2393 input r0 as field; 2394 input r1 as field; 2395 assert.neq r0 r1; 2396 2397 function compute: 2398 input r0 as field.private; 2399 input r1 as field.public; 2400 call check_not_equal r0 r1; 2401 call execute r0 r1 into r2 r3 r4; 2402 output r2 as field.private; 2403 output r3 as field.private; 2404 output r4 as field.private;", 2405 ) 2406 .unwrap(); 2407 assert!(string.is_empty(), "Parser did not consume all of the string: '{string}'"); 2408 2409 // Declare the function name. 2410 let function_name = Identifier::from_str("compute").unwrap(); 2411 2412 // Initialize the RNG. 2413 let rng = &mut TestRng::default(); 2414 2415 // Construct the process. 2416 let process = crate::test_helpers::sample_process(&program); 2417 // Check that the circuit key can be synthesized. 2418 process.synthesize_key::<CurrentAleo, _>(program.id(), &function_name, rng).unwrap(); 2419 2420 // Reset the process. 2421 let process = crate::test_helpers::sample_process(&program); 2422 2423 // Initialize a new caller account. 2424 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 2425 2426 // Declare the input value. 2427 let r0 = Value::<CurrentNetwork>::from_str("3field").unwrap(); 2428 let r1 = Value::<CurrentNetwork>::from_str("5field").unwrap(); 2429 2430 // Authorize the function call. 2431 let authorization = process 2432 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), function_name, [r0, r1].iter(), rng) 2433 .unwrap(); 2434 assert_eq!(authorization.len(), 1); 2435 2436 let r2 = Value::from_str("19field").unwrap(); 2437 let r3 = Value::from_str("11field").unwrap(); 2438 let r4 = Value::from_str("8field").unwrap(); 2439 2440 // Check again to make sure we didn't modify the authorization before calling `evaluate`. 2441 assert_eq!(authorization.len(), 1); 2442 2443 // Compute the output value. 2444 let response = process.evaluate::<CurrentAleo>(authorization.replicate()).unwrap(); 2445 let candidate = response.outputs(); 2446 assert_eq!(3, candidate.len()); 2447 assert_eq!(r2, candidate[0]); 2448 assert_eq!(r3, candidate[1]); 2449 assert_eq!(r4, candidate[2]); 2450 2451 // Check again to make sure we didn't modify the authorization after calling `evaluate`. 2452 assert_eq!(authorization.len(), 1); 2453 2454 let expected_execution_cost = 2455 execution_cost_for_authorization(&process, &authorization, ConsensusVersion::V10).unwrap(); 2456 2457 // Execute the request. 2458 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 2459 let candidate = response.outputs(); 2460 assert_eq!(3, candidate.len()); 2461 assert_eq!(r2, candidate[0]); 2462 assert_eq!(r3, candidate[1]); 2463 assert_eq!(r4, candidate[2]); 2464 2465 // Initialize a new block store. 2466 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 2467 // Prepare the trace. 2468 trace.prepare(&Query::from(block_store)).unwrap(); 2469 // Prove the execution. 2470 let execution = trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V2, rng).unwrap(); 2471 2472 // Verify the execution. 2473 process.verify_execution(ConsensusVersion::V10, VarunaVersion::V2, InclusionVersion::V1, &execution).unwrap(); 2474 2475 // Check the execution cost 2476 assert_eq!(execution_cost(&process, &execution, ConsensusVersion::V10).unwrap(), expected_execution_cost); 2477 } 2478 2479 #[test] 2480 fn test_process_deploy_credits_program() { 2481 let rng = &mut TestRng::default(); 2482 2483 // Initialize an empty process without the `credits` program. 2484 let empty_process = Process { 2485 universal_srs: UniversalSRS::<CurrentNetwork>::load().unwrap(), 2486 stacks: Default::default(), 2487 old_stacks: Default::default(), 2488 }; 2489 2490 // Construct the process. 2491 let process = Process::load().unwrap(); 2492 2493 // Fetch the credits program 2494 let program = Program::credits().unwrap(); 2495 2496 // Create a deployment for the credits.alpha program. 2497 let deployment = empty_process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 2498 2499 // Ensure the deployment is valid on the empty process. 2500 empty_process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 2501 // Ensure the deployment is not valid on the standard process. 2502 assert!(process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).is_err()); 2503 2504 // Create a new `credits.alpha` program. 2505 let program = Program::from_str( 2506 r" 2507 program credits.alpha; 2508 2509 record token: 2510 owner as address.private; 2511 amount as u64.private; 2512 2513 function compute: 2514 input r0 as u32.private; 2515 add r0 r0 into r1; 2516 output r1 as u32.public;", 2517 ) 2518 .unwrap(); 2519 2520 // Create a deployment for the credits.alpha program. 2521 let deployment = empty_process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 2522 2523 // Ensure the deployment is valid on the empty process. 2524 empty_process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 2525 // Ensure the deployment is not valid on the standard process. 2526 assert!(process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).is_err()); 2527 } 2528 2529 #[test] 2530 fn test_process_zero_input_zero_output_executions() { 2531 // Initialize the RNG. 2532 let rng = &mut TestRng::default(); 2533 2534 // Create a new program with a function that has no inputs or outputs. 2535 let function_name = Identifier::from_str("zero_inputs_zero_outputs").unwrap(); 2536 let program = Program::from_str(&format!( 2537 r" 2538 program testing.alpha; 2539 function {function_name}: 2540 add 0u8 1u8 into r0;", 2541 )) 2542 .unwrap(); 2543 2544 // Reset the process. 2545 let mut process = Process::load().unwrap(); 2546 2547 // Initialize a new block store. 2548 let block_store = BlockStore::<CurrentNetwork, BlockMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 2549 // Initialize a new finalize store. 2550 let finalize_store = FinalizeStore::<_, FinalizeMemory<_>>::open(StorageMode::new_test(None)).unwrap(); 2551 2552 // Add the program to the process. 2553 let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 2554 // Check that the deployment verifies. 2555 process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V10, &deployment, rng).unwrap(); 2556 // Compute the fee. 2557 let fee = sample_fee::<_, CurrentAleo, _, _>(&process, &block_store, &finalize_store, rng); 2558 // Finalize the deployment. 2559 let (stack, _) = process.finalize_deployment(sample_finalize_state(1), &finalize_store, &deployment, &fee).unwrap(); 2560 // Add the stack *manually* to the process. 2561 process.add_stack(stack); 2562 2563 // Initialize a new caller account. 2564 let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap(); 2565 2566 // Create an execution for the `zero_inputs_zero_outputs` function. 2567 let execution_1 = { 2568 // Authorize the function call. 2569 let inputs = Vec::<Value<CurrentNetwork>>::new(); 2570 let authorization = process 2571 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), &function_name, inputs.iter(), rng) 2572 .unwrap(); 2573 2574 // Execute the request. 2575 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 2576 assert_eq!(response.outputs().len(), 0); 2577 2578 // Prepare the trace. 2579 trace.prepare(&Query::from(block_store.clone())).unwrap(); 2580 // Prove the execution. 2581 trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V2, rng).unwrap() 2582 }; 2583 assert_eq!(execution_1.len(), 1); 2584 2585 // Create a subsequent execution for the `zero_inputs_zero_outputs` function. 2586 let execution_2 = { 2587 // Authorize the function call. 2588 let inputs = Vec::<Value<CurrentNetwork>>::new(); 2589 let authorization = process 2590 .authorize::<CurrentAleo, _>(&caller_private_key, program.id(), &function_name, inputs.iter(), rng) 2591 .unwrap(); 2592 2593 // Execute the request. 2594 let (response, mut trace) = process.execute::<CurrentAleo, _>(authorization, rng).unwrap(); 2595 assert_eq!(response.outputs().len(), 0); 2596 2597 // Prepare the trace. 2598 trace.prepare(&Query::from(block_store)).unwrap(); 2599 // Prove the execution. 2600 trace.prove_execution::<CurrentAleo, _>("testing", VarunaVersion::V2, rng).unwrap() 2601 }; 2602 assert_eq!(execution_2.len(), 1); 2603 2604 // Ensure that the transitions are unique. 2605 assert_ne!(execution_1.peek().unwrap().id(), execution_2.peek().unwrap().id()); 2606 assert_ne!(execution_1.to_execution_id().unwrap(), execution_2.to_execution_id().unwrap()); 2607 } 2608 2609 #[test] 2610 fn test_long_import_chain() { 2611 const MAX_PROGRAM_DEPTH: usize = 64; 2612 // Initialize a new program. 2613 let program = Program::<CurrentNetwork>::from_str( 2614 r" 2615 program test0.alpha; 2616 function c:", 2617 ) 2618 .unwrap(); 2619 2620 // Construct the process. 2621 let mut process = crate::test_helpers::sample_process(&program); 2622 2623 // Add `MAX_PROGRAM_DEPTH` programs to the process. 2624 for i in 1..=MAX_PROGRAM_DEPTH { 2625 println!("Adding program {i}"); 2626 // Initialize a new program. 2627 let program = Program::from_str(&format!( 2628 " 2629 import test{}.alpha; 2630 program test{}.alpha; 2631 function c:", 2632 i - 1, 2633 i 2634 )) 2635 .unwrap(); 2636 // Add the program to the process. 2637 process.add_program(&program).unwrap(); 2638 } 2639 2640 // Add the `MAX_PROGRAM_DEPTH + 1` program to the process, which should fail. 2641 let program = Program::from_str(&format!( 2642 " 2643 import test{}.alpha; 2644 program test{}.alpha; 2645 function c:", 2646 MAX_PROGRAM_DEPTH, 2647 MAX_PROGRAM_DEPTH + 1 2648 )) 2649 .unwrap(); 2650 let result = process.add_program(&program); 2651 // Programs may create long import chains as long as number of calls does not exceed the maximum number of transitions. 2652 assert!(result.is_ok()); 2653 } 2654 2655 #[test] 2656 fn test_long_import_chain_with_calls() { 2657 // Initialize a new program. 2658 let program = Program::<CurrentNetwork>::from_str( 2659 r" 2660 program test0.alpha; 2661 function c:", 2662 ) 2663 .unwrap(); 2664 2665 // Construct the process. 2666 let mut process = crate::test_helpers::sample_process(&program); 2667 2668 // Check that the number of calls, up to `Transaction::MAX_TRANSITIONS - 1`, is correct. 2669 for i in 1..(Transaction::<CurrentNetwork>::MAX_TRANSITIONS - 1) { 2670 println!("Adding program {i}"); 2671 // Initialize a new program. 2672 let program = Program::from_str(&format!( 2673 " 2674 import test{}.alpha; 2675 program test{}.alpha; 2676 function c: 2677 call test{}.alpha/c;", 2678 i - 1, 2679 i, 2680 i - 1 2681 )) 2682 .unwrap(); 2683 // Add the program to the process. 2684 process.add_program(&program).unwrap(); 2685 // Check that the number of calls is correct. 2686 let stack = process.get_stack(program.id()).unwrap(); 2687 let number_of_calls = stack.get_number_of_calls(program.functions().into_iter().next().unwrap().0).unwrap(); 2688 assert_eq!(number_of_calls, i + 1); 2689 } 2690 2691 // Check that `Transaction::MAX_TRANSITIONS - 1`-th call fails. 2692 let program = Program::from_str(&format!( 2693 " 2694 import test{}.alpha; 2695 program test{}.alpha; 2696 function c: 2697 call test{}.alpha/c;", 2698 Transaction::<CurrentNetwork>::MAX_TRANSITIONS - 2, 2699 Transaction::<CurrentNetwork>::MAX_TRANSITIONS - 1, 2700 Transaction::<CurrentNetwork>::MAX_TRANSITIONS - 2 2701 )) 2702 .unwrap(); 2703 let result = process.add_program(&program); 2704 assert!(result.is_err()) 2705 } 2706 2707 #[test] 2708 fn test_max_imports() { 2709 // Construct the process. 2710 let mut process = Process::<CurrentNetwork>::load().unwrap(); 2711 2712 // Add `MAX_IMPORTS` programs to the process. 2713 for i in 0..CurrentNetwork::MAX_IMPORTS { 2714 println!("Adding program {i}"); 2715 // Initialize a new program. 2716 let program = Program::from_str(&format!("program test{i}.alpha; function c:")).unwrap(); 2717 // Add the program to the process. 2718 process.add_program(&program).unwrap(); 2719 } 2720 2721 // Add a program importing all `MAX_IMPORTS` programs, which should pass. 2722 let import_string = 2723 (0..CurrentNetwork::MAX_IMPORTS).map(|i| format!("import test{i}.alpha;")).collect::<Vec<_>>().join(" "); 2724 let program = 2725 Program::from_str(&format!("{import_string}program test{}.alpha; function c:", CurrentNetwork::MAX_IMPORTS)) 2726 .unwrap(); 2727 process.add_program(&program).unwrap(); 2728 2729 // Attempt to construct a program importing `MAX_IMPORTS + 1` programs, which should fail. 2730 let import_string = 2731 (0..CurrentNetwork::MAX_IMPORTS + 1).map(|i| format!("import test{i}.alpha;")).collect::<Vec<_>>().join(" "); 2732 let result = Program::<CurrentNetwork>::from_str(&format!( 2733 "{import_string}program test{}.alpha; function c:", 2734 CurrentNetwork::MAX_IMPORTS + 1 2735 )); 2736 assert!(result.is_err()); 2737 } 2738 2739 #[test] 2740 fn test_program_exceeding_transaction_spend_limit() { 2741 // Construct a finalize body whose finalize cost is excessively large. 2742 let mut finalize_body = r" 2743 cast 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 0u8 into r0 as [u8; 16u32]; 2744 cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [[u8; 16u32]; 16u32]; 2745 cast r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 r1 into r2 as [[[u8; 16u32]; 16u32]; 16u32];" 2746 .to_string(); 2747 (3..500).for_each(|i| { 2748 finalize_body.push_str(&format!("hash.bhp256 r2 into r{i} as field;\n")); 2749 }); 2750 // Construct the program. 2751 let program = Program::from_str(&format!( 2752 r"program test_max_spend_limit.alpha; 2753 function foo: 2754 async foo into r0; 2755 output r0 as test_max_spend_limit.alpha/foo.future; 2756 2757 finalize foo:{finalize_body}", 2758 )) 2759 .unwrap(); 2760 2761 // Initialize a `Process`. 2762 let process = Process::<CurrentNetwork>::load().unwrap(); 2763 2764 // Attempt to deploy the program, which should succeed. 2765 let rng = &mut TestRng::default(); 2766 let deployment = process.deploy::<CurrentAleo, _>(&program, rng).unwrap(); 2767 // Attempt to verify the deployment, which should fail. 2768 assert!(process.verify_deployment::<CurrentAleo, _>(ConsensusVersion::V8, &deployment, rng).is_ok()); 2769 }