/ synthesizer / src / vm / mod.rs
mod.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  mod helpers;
  17  pub use helpers::*;
  18  
  19  mod authorize;
  20  mod deploy;
  21  mod execute;
  22  mod finalize;
  23  mod verify;
  24  
  25  #[cfg(test)]
  26  mod tests;
  27  
  28  use crate::{Restrictions, cast_mut_ref, cast_ref, convert, process};
  29  use alphavm_algorithms::snark::varuna::VarunaVersion;
  30  use alphavm_ledger_block::{
  31      Block,
  32      ConfirmedTransaction,
  33      Deployment,
  34      Execution,
  35      Fee,
  36      Header,
  37      Output,
  38      Ratifications,
  39      Ratify,
  40      Rejected,
  41      Solutions,
  42      Transaction,
  43      Transactions,
  44  };
  45  use alphavm_ledger_committee::Committee;
  46  use alphavm_ledger_narwhal_data::Data;
  47  use alphavm_ledger_puzzle::Puzzle;
  48  use alphavm_ledger_query::{Query, QueryTrait};
  49  use alphavm_ledger_store::{
  50      BlockStore,
  51      ConsensusStorage,
  52      ConsensusStore,
  53      FinalizeMode,
  54      FinalizeStore,
  55      TransactionStore,
  56      TransitionStore,
  57      atomic_finalize,
  58  };
  59  use alphavm_synthesizer_process::{
  60      Authorization,
  61      InclusionVersion,
  62      Process,
  63      Trace,
  64      deployment_cost,
  65      execute_compute_cost_in_microcredits,
  66      execution_cost,
  67  };
  68  use alphavm_synthesizer_program::{
  69      FinalizeGlobalState,
  70      FinalizeOperation,
  71      FinalizeStoreTrait,
  72      Program,
  73      StackTrait as _,
  74  };
  75  use alphavm_synthesizer_snark::VerifyingKey;
  76  use alphavm_utilities::try_vm_runtime;
  77  use console::{
  78      account::{Address, PrivateKey},
  79      network::prelude::*,
  80      program::{Argument, Identifier, Literal, Locator, Plaintext, ProgramID, ProgramOwner, Record, Response, Value},
  81      types::{Field, Group, U16, U64},
  82  };
  83  
  84  use alpha_std::prelude::{finish, lap, timer};
  85  use anyhow::Context;
  86  use indexmap::{IndexMap, IndexSet};
  87  use itertools::Either;
  88  #[cfg(feature = "locktick")]
  89  use locktick::parking_lot::{Mutex, RwLock};
  90  use lru::LruCache;
  91  #[cfg(not(feature = "locktick"))]
  92  use parking_lot::{Mutex, RwLock};
  93  use rand::{SeedableRng, rngs::StdRng};
  94  use std::{
  95      collections::HashSet,
  96      num::NonZeroUsize,
  97      sync::{Arc, mpsc},
  98      thread,
  99  };
 100  
 101  #[cfg(not(feature = "serial"))]
 102  use rayon::prelude::*;
 103  
 104  // The key for the partially-verified transactions cache.
 105  // The key is a tuple of the transaction ID and a list of program checksums for the transitions in the transaction.
 106  // Note: If a program is upgraded and its contents are changed, then the program checksums will change, invalidating the previously cached result.
 107  type TransactionCacheKey<N> = (<N as Network>::TransactionID, Vec<U16<N>>);
 108  
 109  #[derive(Clone)]
 110  pub struct VM<N: Network, C: ConsensusStorage<N>> {
 111      /// The process.
 112      process: Arc<RwLock<Process<N>>>,
 113      /// The puzzle.
 114      puzzle: Puzzle<N>,
 115      /// The VM store.
 116      store: ConsensusStore<N, C>,
 117      /// A cache containing the list of recent partially-verified transactions.
 118      partially_verified_transactions: Arc<RwLock<LruCache<TransactionCacheKey<N>, N::TransmissionChecksum>>>,
 119      /// The restrictions list.
 120      restrictions: Restrictions<N>,
 121      /// A sender to the channel for operations that must be performed sequentially.
 122      sequential_ops_tx: Arc<RwLock<Option<mpsc::Sender<SequentialOperationRequest<N>>>>>,
 123      /// The handle to the thread which processes operations sequentially.
 124      sequential_ops_thread: Arc<Mutex<Option<thread::JoinHandle<()>>>>,
 125  }
 126  
 127  impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
 128      /// Initializes the VM from storage.
 129      #[inline]
 130      pub fn from(store: ConsensusStore<N, C>) -> Result<Self> {
 131          // Initialize the store for 'credits.alpha'.
 132          let credits = Program::<N>::credits()?;
 133          for mapping in credits.mappings().values() {
 134              // Ensure that all mappings are initialized.
 135              if !store.finalize_store().contains_mapping_confirmed(credits.id(), mapping.name())? {
 136                  // Initialize the mappings for 'credits.alpha'.
 137                  store.finalize_store().initialize_mapping(*credits.id(), *mapping.name())?;
 138              }
 139          }
 140  
 141          // Retrieve the transaction store.
 142          let transaction_store = store.transaction_store();
 143          // Retrieve the block store.
 144          let block_store = store.block_store();
 145  
 146          #[cfg(not(any(test, feature = "test")))]
 147          let mut process = {
 148              // Determine the latest block height.
 149              let latest_block_height = block_store.current_block_height();
 150              // Determine the consensus version.
 151              let consensus_version = N::CONSENSUS_VERSION(latest_block_height)?; // TODO (raychu86): Record Commitment - Select the proper consensus version.
 152              // Initialize a new process based on the consensus version.
 153              if (ConsensusVersion::V1..=ConsensusVersion::V7).contains(&consensus_version) {
 154                  Process::load_v0()?
 155              } else {
 156                  Process::load()?
 157              }
 158          };
 159          #[cfg(any(test, feature = "test"))]
 160          // Initialize a new process.
 161          let mut process = Process::load()?;
 162  
 163          // Retrieve the list of deployment transaction IDs and their associated block heights.
 164          let deployment_ids = transaction_store.deployment_transaction_ids().collect::<Vec<_>>();
 165          let mut deployment_ids = cfg_into_iter!(deployment_ids)
 166              .map(|transaction_id| {
 167                  // Retrieve the block hash for the deployment transaction ID.
 168                  let Some(hash) = block_store.find_block_hash(&transaction_id)? else {
 169                      bail!("Deployment transaction '{transaction_id}' is not found in storage.")
 170                  };
 171                  // Retrieve the height.
 172                  let Some(height) = block_store.get_block_height(&hash)? else {
 173                      bail!("Block height for deployment transaction '{transaction_id}' is not found in storage.")
 174                  };
 175                  // Get the corresponding block's transactions.
 176                  let Some(transactions) = block_store.get_block_transactions(&hash)? else {
 177                      bail!("Transactions for deployment transaction '{hash}' is not found in storage.")
 178                  };
 179                  // Find the index of the deployment transaction ID in the block's transactions.
 180                  let Some(index) = transactions.index_of(transaction_id.deref()) else {
 181                      bail!("Transaction for deployment transaction '{transaction_id}' is not found in storage.")
 182                  };
 183                  Ok((transaction_id, (height, index)))
 184              })
 185              .collect::<Result<Vec<_>>>()?;
 186          // Sort the deployment transaction IDs by their block heights.
 187          deployment_ids.sort_unstable_by(|(_, a), (_, b)| a.cmp(b));
 188  
 189          // Load the deployments in order of their block heights.
 190          const PARALLELIZATION_FACTOR: usize = 256;
 191          for (i, chunk) in deployment_ids.chunks(PARALLELIZATION_FACTOR).enumerate() {
 192              debug!(
 193                  "Loading deployments {}-{} (of {})...",
 194                  i * PARALLELIZATION_FACTOR,
 195                  ((i + 1) * PARALLELIZATION_FACTOR).min(deployment_ids.len()),
 196                  deployment_ids.len()
 197              );
 198              // Load the deployments.
 199              let deployments = cfg_iter!(chunk)
 200                  .map(|(transaction_id, _)| {
 201                      // Retrieve the deployment from the transaction ID.
 202                      match transaction_store.get_deployment(transaction_id)? {
 203                          Some(deployment) => Ok(deployment),
 204                          None => bail!("Deployment transaction '{transaction_id}' is not found in storage."),
 205                      }
 206                  })
 207                  .collect::<Result<Vec<_>>>()?;
 208              // Add the deployments to the process.
 209              // Note: This iterator must be serial, to ensure deployments are loaded in the order of their dependencies.
 210              // NOTE: Program deployment is disabled. Only credits.alpha is supported.
 211              // Skip loading any non-credits deployments (they shouldn't exist in a properly configured chain).
 212              deployments.iter().try_for_each(|deployment| {
 213                  let program_id = deployment.program_id();
 214                  if program_id.to_string() != "credits.alpha" {
 215                      warn!("Skipping non-credits deployment: {program_id} (deployment is disabled on ALPHA chain)");
 216                      return Ok(());
 217                  }
 218                  process.load_deployment(deployment)
 219              })?;
 220          }
 221  
 222          // Construct the VM object.
 223          let vm = Self {
 224              process: Arc::new(RwLock::new(process)),
 225              puzzle: Self::new_puzzle()?,
 226              store,
 227              partially_verified_transactions: Arc::new(RwLock::new(LruCache::new(
 228                  NonZeroUsize::new(Transactions::<N>::MAX_TRANSACTIONS).unwrap(),
 229              ))),
 230              restrictions: Restrictions::load()?,
 231              sequential_ops_tx: Default::default(),
 232              sequential_ops_thread: Default::default(),
 233          };
 234  
 235          // Spawn a thread for sequential operations.
 236          let (sequential_ops_tx, sequential_ops_rx) = mpsc::channel();
 237          let sequential_ops_thread = vm.start_sequential_queue(sequential_ops_rx);
 238  
 239          // Populate the fields related to the sequential operations.
 240          *vm.sequential_ops_tx.write() = Some(sequential_ops_tx);
 241          *vm.sequential_ops_thread.lock() = Some(sequential_ops_thread);
 242  
 243          // Return the new VM.
 244          Ok(vm)
 245      }
 246  
 247      /// Returns `true` if a program with the given program ID exists.
 248      #[inline]
 249      pub fn contains_program(&self, program_id: &ProgramID<N>) -> bool {
 250          self.process.read().contains_program(program_id)
 251      }
 252  
 253      /// Returns the process.
 254      #[inline]
 255      pub fn process(&self) -> Arc<RwLock<Process<N>>> {
 256          self.process.clone()
 257      }
 258  
 259      /// Returns the puzzle.
 260      #[inline]
 261      pub const fn puzzle(&self) -> &Puzzle<N> {
 262          &self.puzzle
 263      }
 264  
 265      /// Returns the partially-verified transactions.
 266      #[inline]
 267      pub fn partially_verified_transactions(
 268          &self,
 269      ) -> Arc<RwLock<LruCache<TransactionCacheKey<N>, N::TransmissionChecksum>>> {
 270          self.partially_verified_transactions.clone()
 271      }
 272  
 273      /// Returns the restrictions.
 274      #[inline]
 275      pub const fn restrictions(&self) -> &Restrictions<N> {
 276          &self.restrictions
 277      }
 278  }
 279  
 280  impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
 281      /// Returns the finalize store.
 282      #[inline]
 283      pub fn finalize_store(&self) -> &FinalizeStore<N, C::FinalizeStorage> {
 284          self.store.finalize_store()
 285      }
 286  
 287      /// Returns the block store.
 288      #[inline]
 289      pub fn block_store(&self) -> &BlockStore<N, C::BlockStorage> {
 290          self.store.block_store()
 291      }
 292  
 293      /// Returns the transaction store.
 294      #[inline]
 295      pub fn transaction_store(&self) -> &TransactionStore<N, C::TransactionStorage> {
 296          self.store.transaction_store()
 297      }
 298  
 299      /// Returns the transition store.
 300      #[inline]
 301      pub fn transition_store(&self) -> &TransitionStore<N, C::TransitionStorage> {
 302          self.store.transition_store()
 303      }
 304  }
 305  
 306  impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
 307      /// Returns a new instance of the puzzle.
 308      pub fn new_puzzle() -> Result<Puzzle<N>> {
 309          // Initialize a new instance of the puzzle.
 310          macro_rules! logic {
 311              ($network:path, $aleo:path) => {{
 312                  let puzzle = Puzzle::new::<alphavm_ledger_puzzle_epoch::SynthesisPuzzle<$network, $aleo>>();
 313                  Ok(cast_ref!(puzzle as Puzzle<N>).clone())
 314              }};
 315          }
 316          // Initialize the puzzle.
 317          convert!(logic)
 318      }
 319  }
 320  
 321  impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
 322      /// Returns a new genesis block for a beacon chain with the default size (four validators).
 323      pub fn genesis_beacon<R: Rng + CryptoRng>(&self, private_key: &PrivateKey<N>, rng: &mut R) -> Result<Block<N>> {
 324          self.genesis_beacon_with_size(private_key, 4, rng)
 325      }
 326  
 327      /// Returns a new genesis block for a beacon chain.
 328      pub fn genesis_beacon_with_size<R: Rng + CryptoRng>(
 329          &self,
 330          private_key: &PrivateKey<N>,
 331          num_validators: usize,
 332          rng: &mut R,
 333      ) -> Result<Block<N>> {
 334          ensure!(num_validators >= 4, "Need at least four validators");
 335  
 336          let mut private_keys = vec![*private_key];
 337          for _ in 1..num_validators {
 338              private_keys.push(PrivateKey::new(rng)?);
 339          }
 340  
 341          // Construct the committee members.
 342          let mut members = IndexMap::with_capacity(num_validators);
 343          for key in &private_keys {
 344              let addr = Address::try_from(key)?;
 345              members.insert(addr, (alphavm_ledger_committee::MIN_VALIDATOR_STAKE, true, 0u8));
 346          }
 347  
 348          // Construct the committee.
 349          let committee = Committee::<N>::new_genesis(members)?;
 350  
 351          // Compute the remaining supply.
 352          let remaining_supply = N::STARTING_SUPPLY
 353              .checked_sub(alphavm_ledger_committee::MIN_VALIDATOR_STAKE * (num_validators as u64))
 354              .with_context(|| "Not enough starting supply for this many validators")?;
 355  
 356          // Construct the public balances.
 357          let mut public_balances = IndexMap::with_capacity(4);
 358          for key in &private_keys {
 359              let addr = Address::try_from(key)?;
 360              public_balances.insert(addr, remaining_supply / num_validators as u64);
 361          }
 362  
 363          // Construct the bonded balances.
 364          let bonded_balances = committee
 365              .members()
 366              .iter()
 367              .map(|(address, (amount, _, _))| (*address, (*address, *address, *amount)))
 368              .collect();
 369  
 370          // Return the genesis block.
 371          self.genesis_quorum(private_key, committee, public_balances, bonded_balances, rng)
 372      }
 373  
 374      /// Returns a new genesis block for a quorum chain.
 375      ///
 376      /// # Panics
 377      /// This function panics if called from an async context.
 378      pub fn genesis_quorum<R: Rng + CryptoRng>(
 379          &self,
 380          private_key: &PrivateKey<N>,
 381          committee: Committee<N>,
 382          public_balances: IndexMap<Address<N>, u64>,
 383          bonded_balances: IndexMap<Address<N>, (Address<N>, Address<N>, u64)>,
 384          rng: &mut R,
 385      ) -> Result<Block<N>> {
 386          // Retrieve the total bonded balance.
 387          let total_bonded_amount = bonded_balances
 388              .values()
 389              .try_fold(0u64, |acc, (_, _, x)| acc.checked_add(*x).ok_or(anyhow!("Invalid bonded amount")))?;
 390          // Compute the account supply.
 391          let account_supply = public_balances
 392              .values()
 393              .try_fold(0u64, |acc, x| acc.checked_add(*x).ok_or(anyhow!("Invalid account supply")))?;
 394          // Compute the total supply.
 395          let total_supply =
 396              total_bonded_amount.checked_add(account_supply).ok_or_else(|| anyhow!("Invalid total supply"))?;
 397          // Ensure the total supply matches.
 398          ensure!(
 399              total_supply == N::STARTING_SUPPLY,
 400              "Invalid total supply. Found {total_supply}, expected {}",
 401              N::STARTING_SUPPLY
 402          );
 403  
 404          // Prepare the caller.
 405          let caller = Address::try_from(private_key)?;
 406          // Prepare the locator.
 407          let locator = ("credits.alpha", "transfer_public_to_private");
 408          // Prepare the amount for each call to the function.
 409          let amount = public_balances
 410              .get(&caller)
 411              .ok_or_else(|| anyhow!("Missing public balance for {caller}"))?
 412              .saturating_div(Block::<N>::NUM_GENESIS_TRANSACTIONS.saturating_mul(2) as u64);
 413          // Prepare the function inputs.
 414          let inputs = [caller.to_string(), format!("{amount}_u64")];
 415  
 416          // Prepare the ratifications.
 417          let ratifications =
 418              vec![Ratify::Genesis(Box::new(committee), Box::new(public_balances), Box::new(bonded_balances))];
 419          // Prepare the solutions.
 420          let solutions = Solutions::<N>::from(None); // The genesis block does not require solutions.
 421          // Prepare the aborted solution IDs.
 422          let aborted_solution_ids = vec![];
 423          // Prepare the transactions.
 424          let transactions = (0..Block::<N>::NUM_GENESIS_TRANSACTIONS)
 425              .map(|_| self.execute(private_key, locator, inputs.iter(), None, 0, None, rng))
 426              .collect::<Result<Vec<_>, _>>()?;
 427  
 428          // Construct the finalize state.
 429          let state = FinalizeGlobalState::new_genesis::<N>()?;
 430          // Speculate on the ratifications, solutions, and transactions.
 431          let (ratifications, transactions, aborted_transaction_ids, ratified_finalize_operations) =
 432              self.speculate(state, 0, None, ratifications, &solutions, transactions.iter(), rng)?;
 433          ensure!(
 434              aborted_transaction_ids.is_empty(),
 435              "Failed to initialize a genesis block - found aborted transaction IDs"
 436          );
 437  
 438          // Prepare the block header.
 439          let header = Header::genesis(&ratifications, &transactions, ratified_finalize_operations)?;
 440          // Prepare the previous block hash.
 441          let previous_hash = N::BlockHash::default();
 442  
 443          // Construct the block.
 444          let block = Block::new_beacon(
 445              private_key,
 446              previous_hash,
 447              header,
 448              ratifications,
 449              solutions,
 450              aborted_solution_ids,
 451              transactions,
 452              aborted_transaction_ids,
 453              rng,
 454          )?;
 455          // Ensure the block is valid genesis block.
 456          match block.is_genesis()? {
 457              true => Ok(block),
 458              false => bail!("Failed to initialize a genesis block"),
 459          }
 460      }
 461  
 462      /// Adds the given block into the VM.
 463      ///
 464      /// # Panics
 465      /// This function panics if called from an async context.
 466      #[inline]
 467      pub fn add_next_block(&self, block: &Block<N>) -> Result<()> {
 468          let sequential_op = SequentialOperation::AddNextBlock(block.clone());
 469          let Some(SequentialOperationResult::AddNextBlock(ret)) = self.run_sequential_operation(sequential_op) else {
 470              bail!("Already shutting down");
 471          };
 472  
 473          ret
 474      }
 475  
 476      /// Adds the given block into the VM.
 477      ///
 478      /// # Note
 479      /// This must only be called from the sequential operation thread.
 480      ///
 481      /// # Panics
 482      /// This function panics if not called from the sequential operation thread.
 483      #[inline]
 484      pub(crate) fn add_next_block_inner(&self, block: Block<N>) -> Result<()> {
 485          self.ensure_sequential_processing();
 486  
 487          // Determine if the block timestamp should be included.
 488          let block_timestamp = (block.height() >= N::CONSENSUS_HEIGHT(ConsensusVersion::V12).unwrap_or_default())
 489              .then_some(block.timestamp());
 490          // Construct the finalize state.
 491          let state = FinalizeGlobalState::new::<N>(
 492              block.round(),
 493              block.height(),
 494              block_timestamp,
 495              block.cumulative_weight(),
 496              block.cumulative_proof_target(),
 497              block.previous_hash(),
 498          )?;
 499  
 500          // Pause the atomic writes, so that both the insertion and finalization belong to a single batch.
 501          #[cfg(feature = "rocks")]
 502          self.block_store().pause_atomic_writes()?;
 503  
 504          // First, insert the block.
 505          if let Err(insert_error) = self.block_store().insert(&block) {
 506              if cfg!(feature = "rocks") {
 507                  // Clear all pending atomic operations so that unpausing the atomic writes
 508                  // doesn't execute any of the queued storage operations.
 509                  self.block_store().abort_atomic();
 510                  // Disable the atomic batch override.
 511                  // Note: This call is guaranteed to succeed (without error), because `DISCARD_BATCH == true`.
 512                  self.block_store().unpause_atomic_writes::<true>()?;
 513              }
 514  
 515              return Err(insert_error);
 516          };
 517  
 518          // Next, finalize the transactions.
 519          match self.finalize(state, block.ratifications(), block.solutions(), block.transactions()) {
 520              Ok(_ratified_finalize_operations) => {
 521                  // If the block advances to `ConsensusVersion::V8`, updated the VKs used for the credits program.
 522                  if N::CONSENSUS_HEIGHT(ConsensusVersion::V8).unwrap_or_default() == block.height() {
 523                      self.update_credits_verifying_keys()?;
 524                  }
 525                  // Unpause the atomic writes, executing the ones queued from block insertion and finalization.
 526                  #[cfg(feature = "rocks")]
 527                  self.block_store().unpause_atomic_writes::<false>()?;
 528                  // If the block advances to a new consensus version, clear the partial verification cache.
 529                  if N::CONSENSUS_VERSION_HEIGHTS().iter().rev().any(|(_, height)| {
 530                      if block.height() < *height {
 531                          // If the block height is less than the consensus version height, break early.
 532                          return false;
 533                      }
 534                      height == &block.height()
 535                  }) {
 536                      self.partially_verified_transactions().write().clear();
 537                  }
 538                  Ok(())
 539              }
 540              Err(finalize_error) => {
 541                  if cfg!(feature = "rocks") {
 542                      // Clear all pending atomic operations so that unpausing the atomic writes
 543                      // doesn't execute any of the queued storage operations.
 544                      self.block_store().abort_atomic();
 545                      self.finalize_store().abort_atomic();
 546                      // Disable the atomic batch override.
 547                      // Note: This call is guaranteed to succeed (without error), because `DISCARD_BATCH == true`.
 548                      self.block_store().unpause_atomic_writes::<true>()?;
 549                      // Rollback the Merkle tree.
 550                      self.block_store().remove_last_n_from_tree_only(1).inspect_err(|_| {
 551                          // Log the finalize error.
 552                          error!("Failed to finalize block {} - {finalize_error}", block.height());
 553                      })?;
 554                  } else {
 555                      // Rollback the block.
 556                      self.block_store().remove_last_n(1).inspect_err(|_| {
 557                          // Log the finalize error.
 558                          error!("Failed to finalize block {} - {finalize_error}", block.height());
 559                      })?;
 560                  }
 561                  // Return the finalize error.
 562                  Err(finalize_error)
 563              }
 564          }
 565      }
 566  }
 567  
 568  impl<N: Network, C: ConsensusStorage<N>> VM<N, C> {
 569      /// Update the `credits.alpha` program in the VM with the latest verifying keys.
 570      fn update_credits_verifying_keys(&self) -> Result<()> {
 571          // Initialize the store for 'credits.alpha'.
 572          let credits = Program::<N>::credits()?;
 573  
 574          // Acquire the process lock.
 575          let process = self.process.write();
 576  
 577          // Synthesize the 'credits.alpha' verifying keys.
 578          for function_name in credits.functions().keys() {
 579              // Remove the proving key.
 580              process.remove_proving_key(credits.id(), function_name)?;
 581              // Load the verifying key.
 582              let verifying_key = N::get_credits_verifying_key(function_name.to_string())?;
 583              // Retrieve the number of public and private variables.
 584              // Note: This number does *NOT* include the number of constants. This is safe because
 585              // this program is never deployed, as it is a first-class citizen of the protocol.
 586              let num_variables = verifying_key.circuit_info.num_public_and_private_variables as u64;
 587              // Insert the verifying key.
 588              process.insert_verifying_key(
 589                  credits.id(),
 590                  function_name,
 591                  VerifyingKey::new(verifying_key.clone(), num_variables),
 592              )?;
 593          }
 594  
 595          Ok(())
 596      }
 597  }
 598  
 599  impl<N: Network, C: ConsensusStorage<N>> Drop for VM<N, C> {
 600      fn drop(&mut self) {
 601          // Check if this the final external reference to `VM`.
 602          if Arc::strong_count(&self.sequential_ops_tx) == 1 {
 603              // If the background thread exists, shut it down.
 604              if let Some(thread) = self.sequential_ops_thread.lock().take() {
 605                  // First, close the channel.
 606                  self.sequential_ops_tx.write().take();
 607                  // Wait for the thread to terminate.
 608                  trace!("Waiting for sequential ops thread to terminate");
 609                  thread.join().expect("Sequential ops thread had an error");
 610              } else {
 611                  debug!("No sequential ops background thread existed durign shutdown");
 612              }
 613          }
 614      }
 615  }
 616  
 617  #[cfg(test)]
 618  pub(crate) mod test_helpers {
 619      use super::*;
 620      use alphavm_ledger_block::{Block, Header, Input, Metadata, Transition};
 621      use alphavm_ledger_test_helpers::{large_transaction_program, small_transaction_program};
 622      use alphavm_synthesizer_program::Program;
 623      use circuit::AleoV0;
 624      use console::{
 625          account::{Address, ViewKey},
 626          network::MainnetV0,
 627          program::{Entry, Value},
 628          types::Field,
 629      };
 630  
 631      use alpha_std::StorageMode;
 632      use alphavm_synthesizer_snark::{Proof, VerifyingKey};
 633      use indexmap::IndexMap;
 634      use serde_json::json;
 635      use std::sync::OnceLock;
 636  
 637      pub(crate) type CurrentNetwork = MainnetV0;
 638      pub(crate) type CurrentAleo = AleoV0;
 639  
 640      #[cfg(not(feature = "rocks"))]
 641      pub(crate) type LedgerType = alphavm_ledger_store::helpers::memory::ConsensusMemory<CurrentNetwork>;
 642      #[cfg(feature = "rocks")]
 643      pub(crate) type LedgerType = alphavm_ledger_store::helpers::rocksdb::ConsensusDB<CurrentNetwork>;
 644  
 645      /// Samples a new finalize state.
 646      pub(crate) fn sample_finalize_state(block_height: u32) -> FinalizeGlobalState {
 647          FinalizeGlobalState::from(block_height as u64, block_height, None, [0u8; 32])
 648      }
 649  
 650      pub(crate) fn sample_vm() -> VM<CurrentNetwork, LedgerType> {
 651          // Initialize a new VM.
 652          VM::from(ConsensusStore::open(StorageMode::new_test(None)).unwrap()).unwrap()
 653      }
 654  
 655      #[cfg(feature = "test")]
 656      pub(crate) fn sample_vm_at_height(height: u32, rng: &mut TestRng) -> VM<CurrentNetwork, LedgerType> {
 657          // Initialize the VM with a genesis block.
 658          let mut vm = sample_vm_with_genesis_block(rng);
 659          // Get the genesis private key.
 660          let genesis_private_key = sample_genesis_private_key(rng);
 661          // Advance the VM to the given height.
 662          advance_vm_to_height(&mut vm, genesis_private_key, height, rng);
 663          // Return the VM.
 664          vm
 665      }
 666  
 667      #[cfg(feature = "test")]
 668      pub(crate) fn advance_vm_to_height(
 669          vm: &mut VM<CurrentNetwork, LedgerType>,
 670          genesis_private_key: PrivateKey<CurrentNetwork>,
 671          height: u32,
 672          rng: &mut TestRng,
 673      ) {
 674          // Advance the VM to the given height.
 675          for _ in vm.block_store().current_block_height()..height {
 676              let block = sample_next_block(vm, &genesis_private_key, &[], rng).unwrap();
 677              vm.add_next_block(&block).unwrap();
 678          }
 679      }
 680  
 681      pub(crate) fn sample_genesis_private_key(rng: &mut TestRng) -> PrivateKey<CurrentNetwork> {
 682          static INSTANCE: OnceLock<PrivateKey<CurrentNetwork>> = OnceLock::new();
 683          *INSTANCE.get_or_init(|| {
 684              // Initialize a new caller.
 685              PrivateKey::<CurrentNetwork>::new(rng).unwrap()
 686          })
 687      }
 688  
 689      pub(crate) fn sample_genesis_block(rng: &mut TestRng) -> Block<CurrentNetwork> {
 690          static INSTANCE: OnceLock<Block<CurrentNetwork>> = OnceLock::new();
 691          INSTANCE
 692              .get_or_init(|| {
 693                  // Initialize the VM.
 694                  let vm = crate::vm::test_helpers::sample_vm();
 695                  // Initialize a new caller.
 696                  let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
 697                  // Return the block.
 698                  vm.genesis_beacon(&caller_private_key, rng).unwrap()
 699              })
 700              .clone()
 701      }
 702  
 703      pub(crate) fn sample_vm_with_genesis_block(rng: &mut TestRng) -> VM<CurrentNetwork, LedgerType> {
 704          // Initialize the VM.
 705          let vm = crate::vm::test_helpers::sample_vm();
 706          // Initialize the genesis block.
 707          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
 708          // Update the VM.
 709          vm.add_next_block(&genesis).unwrap();
 710          // Return the VM.
 711          vm
 712      }
 713  
 714      pub(crate) fn sample_program() -> Program<CurrentNetwork> {
 715          static INSTANCE: OnceLock<Program<CurrentNetwork>> = OnceLock::new();
 716          INSTANCE
 717              .get_or_init(|| {
 718                  // Initialize a new program.
 719                  Program::<CurrentNetwork>::from_str(
 720                      r"
 721  program testing.alpha;
 722  
 723  struct message:
 724      amount as u128;
 725  
 726  mapping account:
 727      key as address.public;
 728      value as u64.public;
 729  
 730  record token:
 731      owner as address.private;
 732      amount as u64.private;
 733  
 734  function initialize:
 735      input r0 as address.private;
 736      input r1 as u64.private;
 737      cast r0 r1 into r2 as token.record;
 738      output r2 as token.record;
 739  
 740  function compute:
 741      input r0 as message.private;
 742      input r1 as message.public;
 743      input r2 as message.private;
 744      input r3 as token.record;
 745      add r0.amount r1.amount into r4;
 746      cast r3.owner r3.amount into r5 as token.record;
 747      output r4 as u128.public;
 748      output r5 as token.record;",
 749                  )
 750                  .unwrap()
 751              })
 752              .clone()
 753      }
 754  
 755      pub(crate) fn sample_deployment_transaction(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
 756          static INSTANCE: OnceLock<Transaction<CurrentNetwork>> = OnceLock::new();
 757          INSTANCE
 758              .get_or_init(|| {
 759                  // Initialize the program.
 760                  let program = sample_program();
 761  
 762                  // Initialize a new caller.
 763                  let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
 764                  let caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
 765  
 766                  // Initialize the genesis block.
 767                  let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
 768  
 769                  // Fetch the unspent records.
 770                  let records =
 771                      genesis.transitions().cloned().flat_map(Transition::into_records).collect::<IndexMap<_, _>>();
 772                  trace!("Unspent Records:\n{:#?}", records);
 773  
 774                  // Prepare the fee.
 775                  let credits = Some(records.values().next().unwrap().decrypt(&caller_view_key).unwrap());
 776  
 777                  // Initialize the VM.
 778                  let vm = sample_vm();
 779                  // Update the VM.
 780                  vm.add_next_block(&genesis).unwrap();
 781  
 782                  // Deploy.
 783                  let transaction = vm.deploy(&caller_private_key, &program, credits, 10, None, rng).unwrap();
 784                  // Verify.
 785                  vm.check_transaction(&transaction, None, rng).unwrap();
 786                  // Return the transaction.
 787                  transaction
 788              })
 789              .clone()
 790      }
 791  
 792      pub(crate) fn sample_execution_transaction_without_fee(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
 793          static INSTANCE: OnceLock<Transaction<CurrentNetwork>> = OnceLock::new();
 794          INSTANCE
 795              .get_or_init(|| {
 796                  // Initialize a new caller.
 797                  let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
 798                  let caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
 799  
 800                  // Initialize the genesis block.
 801                  let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
 802  
 803                  // Fetch the unspent records.
 804                  let records =
 805                      genesis.transitions().cloned().flat_map(Transition::into_records).collect::<IndexMap<_, _>>();
 806                  trace!("Unspent Records:\n{:#?}", records);
 807  
 808                  // Select a record to spend.
 809                  let record = records.values().next().unwrap().decrypt(&caller_view_key).unwrap();
 810  
 811                  // Initialize the VM.
 812                  let vm = sample_vm();
 813                  // Update the VM.
 814                  vm.add_next_block(&genesis).unwrap();
 815  
 816                  // Prepare the inputs.
 817                  let inputs =
 818                      [Value::<CurrentNetwork>::Record(record), Value::<CurrentNetwork>::from_str("1u64").unwrap()]
 819                          .into_iter();
 820  
 821                  // Authorize.
 822                  let authorization = vm.authorize(&caller_private_key, "credits.alpha", "split", inputs, rng).unwrap();
 823                  assert_eq!(authorization.len(), 1);
 824  
 825                  // Construct the execute transaction.
 826                  let transaction = vm.execute_authorization(authorization, None, None, rng).unwrap();
 827                  // Verify.
 828                  vm.check_transaction(&transaction, None, rng).unwrap();
 829                  // Return the transaction.
 830                  transaction
 831              })
 832              .clone()
 833      }
 834  
 835      pub(crate) fn sample_execution_transaction_with_private_fee(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
 836          static INSTANCE: OnceLock<Transaction<CurrentNetwork>> = OnceLock::new();
 837          INSTANCE
 838              .get_or_init(|| {
 839                  // Initialize a new caller.
 840                  let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
 841                  let caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
 842                  let address = Address::try_from(&caller_private_key).unwrap();
 843  
 844                  // Initialize the genesis block.
 845                  let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
 846  
 847                  // Fetch the unspent records.
 848                  let records =
 849                      genesis.transitions().cloned().flat_map(Transition::into_records).collect::<IndexMap<_, _>>();
 850                  trace!("Unspent Records:\n{:#?}", records);
 851  
 852                  // Select a record to spend.
 853                  let record = Some(records.values().next().unwrap().decrypt(&caller_view_key).unwrap());
 854  
 855                  // Initialize the VM.
 856                  let vm = sample_vm();
 857                  // Update the VM.
 858                  vm.add_next_block(&genesis).unwrap();
 859  
 860                  // Prepare the inputs.
 861                  let inputs = [
 862                      Value::<CurrentNetwork>::from_str(&address.to_string()).unwrap(),
 863                      Value::<CurrentNetwork>::from_str("1u64").unwrap(),
 864                  ]
 865                  .into_iter();
 866  
 867                  // Execute.
 868                  let transaction = vm
 869                      .execute(&caller_private_key, ("credits.alpha", "transfer_public"), inputs, record, 0, None, rng)
 870                      .unwrap();
 871                  // Verify.
 872                  vm.check_transaction(&transaction, None, rng).unwrap();
 873                  // Return the transaction.
 874                  transaction
 875              })
 876              .clone()
 877      }
 878  
 879      pub(crate) fn sample_execution_transaction_with_public_fee(rng: &mut TestRng) -> Transaction<CurrentNetwork> {
 880          static INSTANCE: OnceLock<Transaction<CurrentNetwork>> = OnceLock::new();
 881          INSTANCE
 882              .get_or_init(|| {
 883                  // Initialize a new caller.
 884                  let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
 885                  let address = Address::try_from(&caller_private_key).unwrap();
 886  
 887                  // Initialize the genesis block.
 888                  let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
 889  
 890                  // Initialize the VM.
 891                  let vm = sample_vm();
 892                  // Update the VM.
 893                  vm.add_next_block(&genesis).unwrap();
 894  
 895                  // Prepare the inputs.
 896                  let inputs = [
 897                      Value::<CurrentNetwork>::from_str(&address.to_string()).unwrap(),
 898                      Value::<CurrentNetwork>::from_str("1u64").unwrap(),
 899                  ]
 900                  .into_iter();
 901  
 902                  // Execute.
 903                  let transaction_without_fee = vm
 904                      .execute(&caller_private_key, ("credits.alpha", "transfer_public"), inputs, None, 0, None, rng)
 905                      .unwrap();
 906                  let execution = transaction_without_fee.execution().unwrap().clone();
 907  
 908                  // Authorize the fee.
 909                  let authorization = vm
 910                      .authorize_fee_public(
 911                          &caller_private_key,
 912                          10_000_000,
 913                          100,
 914                          execution.to_execution_id().unwrap(),
 915                          rng,
 916                      )
 917                      .unwrap();
 918                  // Compute the fee.
 919                  let fee = vm.execute_fee_authorization(authorization, None, rng).unwrap();
 920  
 921                  // Construct the transaction.
 922                  let transaction = Transaction::from_execution(execution, Some(fee)).unwrap();
 923                  // Verify.
 924                  vm.check_transaction(&transaction, None, rng).unwrap();
 925                  // Return the transaction.
 926                  transaction
 927              })
 928              .clone()
 929      }
 930  
 931      pub fn sample_next_block<R: Rng + CryptoRng>(
 932          vm: &VM<MainnetV0, LedgerType>,
 933          private_key: &PrivateKey<MainnetV0>,
 934          transactions: &[Transaction<MainnetV0>],
 935          rng: &mut R,
 936      ) -> Result<Block<MainnetV0>> {
 937          // Get the most recent block.
 938          let block_hash = vm.block_store().get_block_hash(vm.block_store().max_height().unwrap()).unwrap().unwrap();
 939          let previous_block = vm.block_store().get_block(&block_hash).unwrap().unwrap();
 940  
 941          // Create the finalize state for the next block height.
 942          let next_block_height = previous_block.height() + 1;
 943          let time_since_last_block = MainnetV0::BLOCK_TIME as i64;
 944          let next_block_timestamp = previous_block.timestamp().saturating_add(time_since_last_block);
 945          let next_timestamp = (next_block_height
 946              >= MainnetV0::CONSENSUS_HEIGHT(ConsensusVersion::V12).unwrap_or_default())
 947          .then_some(next_block_timestamp);
 948          let finalize_state =
 949              FinalizeGlobalState::from(next_block_height as u64, next_block_height, next_timestamp, [0u8; 32]);
 950  
 951          // Speculate on the ratifications, solutions, and transactions.
 952          let (ratifications, transactions, aborted_transaction_ids, ratified_finalize_operations) =
 953              vm.speculate(finalize_state, time_since_last_block, None, vec![], &None.into(), transactions.iter(), rng)?;
 954  
 955          // Construct the metadata associated with the block.
 956          let metadata = Metadata::new(
 957              MainnetV0::ID,
 958              previous_block.round() + 1,
 959              previous_block.height() + 1,
 960              0,
 961              0,
 962              MainnetV0::GENESIS_COINBASE_TARGET,
 963              MainnetV0::GENESIS_PROOF_TARGET,
 964              previous_block.last_coinbase_target(),
 965              previous_block.last_coinbase_timestamp(),
 966              previous_block.timestamp().saturating_add(time_since_last_block),
 967          )?;
 968  
 969          // Construct the new block header.
 970          let header = Header::from(
 971              vm.block_store().current_state_root(),
 972              transactions.to_transactions_root().unwrap(),
 973              transactions.to_finalize_root(ratified_finalize_operations).unwrap(),
 974              ratifications.to_ratifications_root().unwrap(),
 975              Field::zero(),
 976              Field::zero(),
 977              metadata,
 978          )?;
 979  
 980          // Construct the new block.
 981          Block::new_beacon(
 982              private_key,
 983              previous_block.hash(),
 984              header,
 985              ratifications,
 986              None.into(),
 987              vec![],
 988              transactions,
 989              aborted_transaction_ids,
 990              rng,
 991          )
 992      }
 993  
 994      #[test]
 995      fn test_multiple_deployments_and_multiple_executions() {
 996          let rng = &mut TestRng::default();
 997  
 998          // Initialize a new caller.
 999          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
1000          let caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
1001  
1002          // Initialize the genesis block.
1003          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
1004  
1005          // Fetch the unspent records.
1006          let records = genesis.transitions().cloned().flat_map(Transition::into_records).collect::<IndexMap<_, _>>();
1007          trace!("Unspent Records:\n{:#?}", records);
1008  
1009          // Select a record to spend.
1010          let record = records.values().next().unwrap().decrypt(&caller_view_key).unwrap();
1011  
1012          // Initialize the VM.
1013          let vm = sample_vm();
1014          // Update the VM.
1015          vm.add_next_block(&genesis).unwrap();
1016  
1017          // Split once.
1018          let transaction = vm
1019              .execute(
1020                  &caller_private_key,
1021                  ("credits.alpha", "split"),
1022                  [Value::Record(record), Value::from_str("1000000000u64").unwrap()].iter(), // 1000 credits
1023                  None,
1024                  0,
1025                  None,
1026                  rng,
1027              )
1028              .unwrap();
1029          let records = transaction.records().collect_vec();
1030          let first_record = records[0].1.clone().decrypt(&caller_view_key).unwrap();
1031          let second_record = records[1].1.clone().decrypt(&caller_view_key).unwrap();
1032          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
1033          vm.add_next_block(&block).unwrap();
1034  
1035          // Split again.
1036          let mut transactions = Vec::new();
1037          let transaction = vm
1038              .execute(
1039                  &caller_private_key,
1040                  ("credits.alpha", "split"),
1041                  [Value::Record(first_record), Value::from_str("100000000u64").unwrap()].iter(), // 100 credits
1042                  None,
1043                  0,
1044                  None,
1045                  rng,
1046              )
1047              .unwrap();
1048          let records = transaction.records().collect_vec();
1049          let first_record = records[0].1.clone().decrypt(&caller_view_key).unwrap();
1050          let third_record = records[1].1.clone().decrypt(&caller_view_key).unwrap();
1051          transactions.push(transaction);
1052          // Split again.
1053          let transaction = vm
1054              .execute(
1055                  &caller_private_key,
1056                  ("credits.alpha", "split"),
1057                  [Value::Record(second_record), Value::from_str("100000000u64").unwrap()].iter(), // 100 credits
1058                  None,
1059                  0,
1060                  None,
1061                  rng,
1062              )
1063              .unwrap();
1064          let records = transaction.records().collect_vec();
1065          let second_record = records[0].1.clone().decrypt(&caller_view_key).unwrap();
1066          let fourth_record = records[1].1.clone().decrypt(&caller_view_key).unwrap();
1067          transactions.push(transaction);
1068          // Add the split transactions to a block and update the VM.
1069          let fee_block = sample_next_block(&vm, &caller_private_key, &transactions, rng).unwrap();
1070          vm.add_next_block(&fee_block).unwrap();
1071  
1072          // Deploy the programs.
1073          let first_program = r"
1074  program test_program_1.alpha;
1075  mapping map_0:
1076      key as field.public;
1077      value as field.public;
1078  function init:
1079      async init into r0;
1080      output r0 as test_program_1.alpha/init.future;
1081  finalize init:
1082      set 0field into map_0[0field];
1083  function getter:
1084      async getter into r0;
1085      output r0 as test_program_1.alpha/getter.future;
1086  finalize getter:
1087      get map_0[0field] into r0;
1088          ";
1089          let second_program = r"
1090  program test_program_2.alpha;
1091  mapping map_0:
1092      key as field.public;
1093      value as field.public;
1094  function init:
1095      async init into r0;
1096      output r0 as test_program_2.alpha/init.future;
1097  finalize init:
1098      set 0field into map_0[0field];
1099  function getter:
1100      async getter into r0;
1101      output r0 as test_program_2.alpha/getter.future;
1102  finalize getter:
1103      get map_0[0field] into r0;
1104          ";
1105          let first_deployment = vm
1106              .deploy(&caller_private_key, &Program::from_str(first_program).unwrap(), Some(first_record), 1, None, rng)
1107              .unwrap();
1108          let second_deployment = vm
1109              .deploy(&caller_private_key, &Program::from_str(second_program).unwrap(), Some(second_record), 1, None, rng)
1110              .unwrap();
1111          let deployment_block =
1112              sample_next_block(&vm, &caller_private_key, &[first_deployment, second_deployment], rng).unwrap();
1113          vm.add_next_block(&deployment_block).unwrap();
1114  
1115          // Execute the programs.
1116          let first_execution = vm
1117              .execute(
1118                  &caller_private_key,
1119                  ("test_program_1.alpha", "init"),
1120                  Vec::<Value<MainnetV0>>::new().iter(),
1121                  Some(third_record),
1122                  1,
1123                  None,
1124                  rng,
1125              )
1126              .unwrap();
1127          let second_execution = vm
1128              .execute(
1129                  &caller_private_key,
1130                  ("test_program_2.alpha", "init"),
1131                  Vec::<Value<MainnetV0>>::new().iter(),
1132                  Some(fourth_record),
1133                  1,
1134                  None,
1135                  rng,
1136              )
1137              .unwrap();
1138          let execution_block =
1139              sample_next_block(&vm, &caller_private_key, &[first_execution, second_execution], rng).unwrap();
1140          vm.add_next_block(&execution_block).unwrap();
1141      }
1142  
1143      #[test]
1144      fn test_load_deployments_with_imports() {
1145          // NOTE: This seed was chosen for the CI's RNG to ensure that the test passes.
1146          let rng = &mut TestRng::fixed(123456789);
1147  
1148          // Initialize a new caller.
1149          let caller_private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
1150          let caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
1151  
1152          // Initialize the VM.
1153          let vm = crate::vm::test_helpers::sample_vm();
1154          // Initialize the genesis block.
1155          let genesis = vm.genesis_beacon(&caller_private_key, rng).unwrap();
1156          // Update the VM.
1157          vm.add_next_block(&genesis).unwrap();
1158  
1159          // Fetch the unspent records.
1160          let records = genesis.transitions().cloned().flat_map(Transition::into_records).collect::<Vec<(_, _)>>();
1161          trace!("Unspent Records:\n{:#?}", records);
1162          let record_0 = records[0].1.decrypt(&caller_view_key).unwrap();
1163          let record_1 = records[1].1.decrypt(&caller_view_key).unwrap();
1164          let record_2 = records[2].1.decrypt(&caller_view_key).unwrap();
1165          let record_3 = records[3].1.decrypt(&caller_view_key).unwrap();
1166  
1167          // Create the deployment for the first program.
1168          let program_1 = r"
1169  program first_program.alpha;
1170  
1171  function c:
1172      input r0 as u8.private;
1173      input r1 as u8.private;
1174      add r0 r1 into r2;
1175      output r2 as u8.private;
1176          ";
1177          let deployment_1 = vm
1178              .deploy(&caller_private_key, &Program::from_str(program_1).unwrap(), Some(record_0), 0, None, rng)
1179              .unwrap();
1180  
1181          // Deploy the first program.
1182          let deployment_block = sample_next_block(&vm, &caller_private_key, &[deployment_1.clone()], rng).unwrap();
1183          vm.add_next_block(&deployment_block).unwrap();
1184  
1185          // Create the deployment for the second program.
1186          let program_2 = r"
1187  import first_program.alpha;
1188  
1189  program second_program.alpha;
1190  
1191  function b:
1192      input r0 as u8.private;
1193      input r1 as u8.private;
1194      call first_program.alpha/c r0 r1 into r2;
1195      output r2 as u8.private;
1196          ";
1197          let deployment_2 = vm
1198              .deploy(&caller_private_key, &Program::from_str(program_2).unwrap(), Some(record_1), 0, None, rng)
1199              .unwrap();
1200  
1201          // Deploy the second program.
1202          let deployment_block = sample_next_block(&vm, &caller_private_key, &[deployment_2.clone()], rng).unwrap();
1203          vm.add_next_block(&deployment_block).unwrap();
1204  
1205          // Create the deployment for the third program.
1206          let program_3 = r"
1207  import second_program.alpha;
1208  
1209  program third_program.alpha;
1210  
1211  function a:
1212      input r0 as u8.private;
1213      input r1 as u8.private;
1214      call second_program.alpha/b r0 r1 into r2;
1215      output r2 as u8.private;
1216          ";
1217          let deployment_3 = vm
1218              .deploy(&caller_private_key, &Program::from_str(program_3).unwrap(), Some(record_2), 0, None, rng)
1219              .unwrap();
1220  
1221          // Create the deployment for the fourth program.
1222          let program_4 = r"
1223  import second_program.alpha;
1224  import first_program.alpha;
1225  
1226  program fourth_program.alpha;
1227  
1228  function a:
1229      input r0 as u8.private;
1230      input r1 as u8.private;
1231      call second_program.alpha/b r0 r1 into r2;
1232      output r2 as u8.private;
1233          ";
1234          let deployment_4 = vm
1235              .deploy(&caller_private_key, &Program::from_str(program_4).unwrap(), Some(record_3), 0, None, rng)
1236              .unwrap();
1237  
1238          // Deploy the third and fourth program together.
1239          let deployment_block =
1240              sample_next_block(&vm, &caller_private_key, &[deployment_3.clone(), deployment_4.clone()], rng).unwrap();
1241          vm.add_next_block(&deployment_block).unwrap();
1242  
1243          // Sanity check the ordering of the deployment transaction IDs from storage.
1244          {
1245              let deployment_transaction_ids =
1246                  vm.transaction_store().deployment_transaction_ids().map(|id| *id).collect::<Vec<_>>();
1247              // This assert check is here to ensure that we are properly loading imports even though any order will work for `VM::from`.
1248              // Note: `deployment_transaction_ids` is sorted lexicographically by transaction ID, so the order may change if we update internal methods.
1249              assert_eq!(
1250                  deployment_transaction_ids,
1251                  vec![deployment_1.id(), deployment_2.id(), deployment_4.id(), deployment_3.id()],
1252                  "Update me if serialization has changed"
1253              );
1254          }
1255  
1256          // Enforce that the VM can load properly with the imports.
1257          assert!(VM::from(vm.store.clone()).is_ok());
1258      }
1259  
1260      #[test]
1261      fn test_multiple_external_calls() {
1262          let rng = &mut TestRng::default();
1263  
1264          // Initialize a new caller.
1265          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
1266          let caller_view_key = ViewKey::try_from(&caller_private_key).unwrap();
1267          let address = Address::try_from(&caller_private_key).unwrap();
1268  
1269          // Initialize the genesis block.
1270          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
1271  
1272          // Fetch the unspent records.
1273          let records =
1274              genesis.transitions().cloned().flat_map(Transition::into_records).take(3).collect::<IndexMap<_, _>>();
1275          trace!("Unspent Records:\n{:#?}", records);
1276          let record_0 = records.values().next().unwrap().decrypt(&caller_view_key).unwrap();
1277          let record_1 = records.values().nth(1).unwrap().decrypt(&caller_view_key).unwrap();
1278          let record_2 = records.values().nth(2).unwrap().decrypt(&caller_view_key).unwrap();
1279  
1280          // Initialize the VM.
1281          let vm = sample_vm();
1282          // Update the VM.
1283          vm.add_next_block(&genesis).unwrap();
1284  
1285          // Deploy the program.
1286          let program = Program::from_str(
1287              r"
1288  import credits.alpha;
1289  
1290  program test_multiple_external_calls.alpha;
1291  
1292  function multitransfer:
1293      input r0 as credits.alpha/credits.record;
1294      input r1 as address.private;
1295      input r2 as u64.private;
1296      call credits.alpha/transfer_private r0 r1 r2 into r3 r4;
1297      call credits.alpha/transfer_private r4 r1 r2 into r5 r6;
1298      output r4 as credits.alpha/credits.record;
1299      output r5 as credits.alpha/credits.record;
1300      output r6 as credits.alpha/credits.record;
1301      ",
1302          )
1303          .unwrap();
1304          let deployment = vm.deploy(&caller_private_key, &program, Some(record_0), 1, None, rng).unwrap();
1305          vm.add_next_block(&sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap()).unwrap();
1306  
1307          // Execute the programs.
1308          let inputs = [
1309              Value::<MainnetV0>::Record(record_1),
1310              Value::<MainnetV0>::from_str(&address.to_string()).unwrap(),
1311              Value::<MainnetV0>::from_str("10u64").unwrap(),
1312          ];
1313          let execution = vm
1314              .execute(
1315                  &caller_private_key,
1316                  ("test_multiple_external_calls.alpha", "multitransfer"),
1317                  inputs.into_iter(),
1318                  Some(record_2),
1319                  1,
1320                  None,
1321                  rng,
1322              )
1323              .unwrap();
1324          vm.add_next_block(&sample_next_block(&vm, &caller_private_key, &[execution], rng).unwrap()).unwrap();
1325      }
1326  
1327      #[test]
1328      fn test_nested_deployment_with_assert() {
1329          let rng = &mut TestRng::default();
1330  
1331          // Initialize a private key.
1332          let private_key = sample_genesis_private_key(rng);
1333  
1334          // Initialize the genesis block.
1335          let genesis = sample_genesis_block(rng);
1336  
1337          // Initialize the VM.
1338          let vm = sample_vm();
1339          // Update the VM.
1340          vm.add_next_block(&genesis).unwrap();
1341  
1342          // Deploy the base program.
1343          let program = Program::from_str(
1344              r"
1345  program child_program.alpha;
1346  
1347  function check:
1348      input r0 as field.private;
1349      assert.eq r0 123456789123456789123456789123456789123456789123456789field;
1350          ",
1351          )
1352          .unwrap();
1353  
1354          let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1355          assert!(vm.check_transaction(&deployment, None, rng).is_ok());
1356          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
1357  
1358          // Check that program is deployed.
1359          assert!(vm.contains_program(&ProgramID::from_str("child_program.alpha").unwrap()));
1360  
1361          // Deploy the program that calls the program from the previous layer.
1362          let program = Program::from_str(
1363              r"
1364  import child_program.alpha;
1365  
1366  program parent_program.alpha;
1367  
1368  function check:
1369      input r0 as field.private;
1370      call child_program.alpha/check r0;
1371          ",
1372          )
1373          .unwrap();
1374  
1375          let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1376          assert!(vm.check_transaction(&deployment, None, rng).is_ok());
1377          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
1378  
1379          // Check that program is deployed.
1380          assert!(vm.contains_program(&ProgramID::from_str("parent_program.alpha").unwrap()));
1381      }
1382  
1383      #[test]
1384      fn test_deployment_with_external_records() {
1385          let rng = &mut TestRng::default();
1386  
1387          // Initialize a private key.
1388          let private_key = sample_genesis_private_key(rng);
1389  
1390          // Initialize the genesis block.
1391          let genesis = sample_genesis_block(rng);
1392  
1393          // Initialize the VM.
1394          let vm = sample_vm();
1395          // Update the VM.
1396          vm.add_next_block(&genesis).unwrap();
1397  
1398          // Deploy the program.
1399          let program = Program::from_str(
1400              r"
1401  import credits.alpha;
1402  program test_program.alpha;
1403  
1404  function transfer:
1405      input r0 as credits.alpha/credits.record;
1406      input r1 as u64.private;
1407      input r2 as u64.private;
1408      input r3 as [address; 10u32].private;
1409      call credits.alpha/transfer_private r0 r3[0u32] r1 into r4 r5;
1410      call credits.alpha/transfer_private r5 r3[0u32] r2 into r6 r7;
1411  ",
1412          )
1413          .unwrap();
1414  
1415          let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1416          assert!(vm.check_transaction(&deployment, None, rng).is_ok());
1417          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
1418  
1419          // Check that program is deployed.
1420          assert!(vm.contains_program(&ProgramID::from_str("test_program.alpha").unwrap()));
1421      }
1422  
1423      #[test]
1424      fn test_internal_fee_calls_are_invalid() {
1425          let rng = &mut TestRng::default();
1426  
1427          // Initialize a private key.
1428          let private_key = sample_genesis_private_key(rng);
1429          let view_key = ViewKey::try_from(&private_key).unwrap();
1430  
1431          // Initialize the genesis block.
1432          let genesis = sample_genesis_block(rng);
1433  
1434          // Initialize the VM.
1435          let vm = sample_vm();
1436          // Update the VM.
1437          vm.add_next_block(&genesis).unwrap();
1438  
1439          // Fetch the unspent records.
1440          let records =
1441              genesis.transitions().cloned().flat_map(Transition::into_records).take(3).collect::<IndexMap<_, _>>();
1442          trace!("Unspent Records:\n{:#?}", records);
1443          let record_0 = records.values().next().unwrap().decrypt(&view_key).unwrap();
1444  
1445          // Deploy the program.
1446          let program = Program::from_str(
1447              r"
1448  import credits.alpha;
1449  program test_program.alpha;
1450  
1451  function call_fee_public:
1452      input r0 as u64.private;
1453      input r1 as u64.private;
1454      input r2 as field.private;
1455      call credits.alpha/fee_public r0 r1 r2 into r3;
1456      async call_fee_public r3 into r4;
1457      output r4 as test_program.alpha/call_fee_public.future;
1458  
1459  finalize call_fee_public:
1460      input r0 as credits.alpha/fee_public.future;
1461      await r0;
1462      
1463  function call_fee_private:
1464      input r0 as credits.alpha/credits.record;
1465      input r1 as u64.private;
1466      input r2 as u64.private;
1467      input r3 as field.private;
1468      call credits.alpha/fee_private r0 r1 r2 r3 into r4;
1469      output r4 as credits.alpha/credits.record;
1470  ",
1471          )
1472          .unwrap();
1473  
1474          let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1475          assert!(vm.check_transaction(&deployment, None, rng).is_ok());
1476          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
1477  
1478          // Execute the programs.
1479          let internal_base_fee_amount: u64 = rng.gen_range(1..1000);
1480          let internal_priority_fee_amount: u64 = rng.gen_range(1..1000);
1481  
1482          // Ensure that the transaction that calls `fee_public` internally cannot be generated.
1483          let inputs = [
1484              Value::<MainnetV0>::from_str(&format!("{internal_base_fee_amount}u64")).unwrap(),
1485              Value::<MainnetV0>::from_str(&format!("{internal_priority_fee_amount}u64")).unwrap(),
1486              Value::<MainnetV0>::from_str("1field").unwrap(),
1487          ];
1488          assert!(
1489              vm.execute(&private_key, ("test_program.alpha", "call_fee_public"), inputs.into_iter(), None, 0, None, rng)
1490                  .is_err()
1491          );
1492  
1493          // Ensure that the transaction that calls `fee_private` internally cannot be generated.
1494          let inputs = [
1495              Value::<MainnetV0>::Record(record_0),
1496              Value::<MainnetV0>::from_str(&format!("{internal_base_fee_amount}u64")).unwrap(),
1497              Value::<MainnetV0>::from_str(&format!("{internal_priority_fee_amount}u64")).unwrap(),
1498              Value::<MainnetV0>::from_str("1field").unwrap(),
1499          ];
1500          assert!(
1501              vm.execute(
1502                  &private_key,
1503                  ("test_program.alpha", "call_fee_private"),
1504                  inputs.into_iter(),
1505                  None,
1506                  0,
1507                  None,
1508                  rng
1509              )
1510              .is_err()
1511          );
1512      }
1513  
1514      #[test]
1515      #[ignore = "memory-intensive"]
1516      fn test_deployment_synthesis_overload() {
1517          let rng = &mut TestRng::default();
1518  
1519          // Initialize a private key.
1520          let private_key = sample_genesis_private_key(rng);
1521  
1522          // Initialize the genesis block.
1523          let genesis = sample_genesis_block(rng);
1524  
1525          // Initialize the VM.
1526          let vm = sample_vm();
1527          // Update the VM.
1528          vm.add_next_block(&genesis).unwrap();
1529  
1530          // Deploy the base program.
1531          let program = Program::from_str(
1532              r"
1533  program synthesis_overload.alpha;
1534  
1535  function do:
1536      input r0 as [[u128; 32u32]; 2u32].private;
1537      hash.sha3_256 r0 into r1 as field;
1538      hash.sha3_256 r0 into r2 as field;
1539      output r2 as field.public;",
1540          )
1541          .unwrap();
1542  
1543          // Create the deployment transaction.
1544          let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1545  
1546          // Verify the deployment transaction. It should fail because there are too many constraints.
1547          assert!(vm.check_transaction(&deployment, None, rng).is_err());
1548      }
1549  
1550      #[test]
1551      fn test_deployment_num_constant_overload() {
1552          let rng = &mut TestRng::default();
1553  
1554          // Initialize a private key.
1555          let private_key = sample_genesis_private_key(rng);
1556  
1557          // Initialize the genesis block.
1558          let genesis = sample_genesis_block(rng);
1559  
1560          // Initialize the VM.
1561          let vm = sample_vm();
1562          // Update the VM.
1563          vm.add_next_block(&genesis).unwrap();
1564  
1565          // Deploy the base program.
1566          let program = Program::from_str(
1567              r"
1568  program synthesis_num_constants.alpha;
1569  function do:
1570      cast 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 into r0 as [u32; 32u32];
1571      cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [[u32; 32u32]; 32u32];
1572      cast r1 r1 r1 r1 r1 into r2 as [[[u32; 32u32]; 32u32]; 5u32];
1573      cast r1 r1 r1 r1 r1 into r3 as [[[u32; 32u32]; 32u32]; 5u32];
1574      hash.bhp1024 r2 into r4 as u32;
1575      hash.bhp1024 r3 into r5 as u32;
1576      output r4 as u32.private;
1577  function do2:
1578      cast 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 0u32 into r0 as [u32; 32u32];
1579      cast r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 r0 into r1 as [[u32; 32u32]; 32u32];
1580      cast r1 r1 r1 r1 r1 into r2 as [[[u32; 32u32]; 32u32]; 5u32];
1581      hash.bhp1024 r2 into r3 as u32;
1582      output r3 as u32.private;",
1583          )
1584              .unwrap();
1585  
1586          // Create the deployment transaction.
1587          let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1588  
1589          // Verify the deployment transaction. It should fail because there are too many constants.
1590          let check_tx_res = vm.check_transaction(&deployment, None, rng);
1591          assert!(check_tx_res.is_err());
1592      }
1593  
1594      #[test]
1595      fn test_deployment_synthesis_overreport() {
1596          let rng = &mut TestRng::default();
1597  
1598          // Initialize a private key.
1599          let private_key = sample_genesis_private_key(rng);
1600  
1601          // Initialize the genesis block.
1602          let genesis = sample_genesis_block(rng);
1603  
1604          // Initialize the VM.
1605          let vm = sample_vm();
1606          // Update the VM.
1607          vm.add_next_block(&genesis).unwrap();
1608  
1609          // Deploy the base program.
1610          let program = Program::from_str(
1611              r"
1612  program synthesis_overreport.alpha;
1613  
1614  function do:
1615      input r0 as u32.private;
1616      add r0 r0 into r1;
1617      output r1 as u32.public;",
1618          )
1619          .unwrap();
1620  
1621          // Create the deployment transaction.
1622          let transaction = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1623  
1624          // Destructure the deployment transaction.
1625          let Transaction::Deploy(_, _, program_owner, deployment, fee) = transaction else {
1626              panic!("Expected a deployment transaction");
1627          };
1628  
1629          // Increase the number of constraints in the verifying keys.
1630          let mut vks_with_overreport = Vec::with_capacity(deployment.verifying_keys().len());
1631          for (id, (vk, cert)) in deployment.verifying_keys() {
1632              let mut vk_deref = vk.deref().clone();
1633              vk_deref.circuit_info.num_constraints += 1;
1634              let vk = VerifyingKey::new(Arc::new(vk_deref), vk.num_variables());
1635              vks_with_overreport.push((*id, (vk, cert.clone())));
1636          }
1637  
1638          // Each additional constraint costs 25 microcredits, so we need to increase the fee by 25 microcredits.
1639          let required_fee = *fee.base_amount().unwrap() + 25;
1640          // Authorize a new fee.
1641          let fee_authorization = vm
1642              .authorize_fee_public(&private_key, required_fee, 0, deployment.as_ref().to_deployment_id().unwrap(), rng)
1643              .unwrap();
1644          // Compute the fee.
1645          let fee = vm.execute_fee_authorization(fee_authorization, None, rng).unwrap();
1646  
1647          // Create a new deployment transaction with the overreported verifying keys.
1648          let adjusted_deployment = Deployment::new(
1649              deployment.edition(),
1650              deployment.program().clone(),
1651              vks_with_overreport,
1652              deployment.program_checksum(),
1653              deployment.program_owner(),
1654          )
1655          .unwrap();
1656          let adjusted_transaction = Transaction::from_deployment(program_owner, adjusted_deployment, fee).unwrap();
1657  
1658          // Verify the deployment transaction. It should error when certificate checking for constraint count mismatch.
1659          let res = vm.check_transaction(&adjusted_transaction, None, rng);
1660          assert!(res.is_err());
1661      }
1662  
1663      #[test]
1664      fn test_deployment_synthesis_underreport() {
1665          let rng = &mut TestRng::default();
1666  
1667          // Initialize a private key.
1668          let private_key = sample_genesis_private_key(rng);
1669          let address = Address::try_from(&private_key).unwrap();
1670  
1671          // Initialize the genesis block.
1672          let genesis = sample_genesis_block(rng);
1673  
1674          // Initialize the VM.
1675          let vm = sample_vm();
1676          // Update the VM.
1677          vm.add_next_block(&genesis).unwrap();
1678  
1679          // Deploy the base program.
1680          let program = Program::from_str(
1681              r"
1682  program synthesis_underreport.alpha;
1683  
1684  function do:
1685      input r0 as u32.private;
1686      add r0 r0 into r1;
1687      output r1 as u32.public;",
1688          )
1689          .unwrap();
1690  
1691          // Create the deployment transaction.
1692          let transaction = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1693  
1694          // Destructure the deployment transaction.
1695          let Transaction::Deploy(txid, _, program_owner, deployment, fee) = transaction else {
1696              panic!("Expected a deployment transaction");
1697          };
1698  
1699          // Decrease the number of constraints in the verifying keys.
1700          let mut vks_with_underreport = Vec::with_capacity(deployment.verifying_keys().len());
1701          for (id, (vk, cert)) in deployment.verifying_keys() {
1702              let mut vk_deref = vk.deref().clone();
1703              vk_deref.circuit_info.num_constraints -= 2;
1704              let vk = VerifyingKey::new(Arc::new(vk_deref), vk.num_variables());
1705              vks_with_underreport.push((*id, (vk, cert.clone())));
1706          }
1707  
1708          // Create a new deployment transaction with the underreported verifying keys.
1709          let adjusted_deployment = Deployment::new(
1710              deployment.edition(),
1711              deployment.program().clone(),
1712              vks_with_underreport,
1713              deployment.program_checksum(),
1714              deployment.program_owner(),
1715          )
1716          .unwrap();
1717          let deployment_id = adjusted_deployment.to_deployment_id().unwrap();
1718          let adjusted_transaction =
1719              Transaction::Deploy(txid, deployment_id, program_owner, Box::new(adjusted_deployment), fee);
1720  
1721          // Verify the deployment transaction. It should error when enforcing the first constraint over the vk limit.
1722          let result = vm.check_transaction(&adjusted_transaction, None, rng);
1723          assert!(result.is_err());
1724  
1725          // Create a standard transaction
1726          // Prepare the inputs.
1727          let inputs = [
1728              Value::<CurrentNetwork>::from_str(&address.to_string()).unwrap(),
1729              Value::<CurrentNetwork>::from_str("1u64").unwrap(),
1730          ]
1731          .into_iter();
1732  
1733          // Execute.
1734          let transaction =
1735              vm.execute(&private_key, ("credits.alpha", "transfer_public"), inputs, None, 0, None, rng).unwrap();
1736  
1737          // Check that the deployment transaction will be aborted if injected into a block.
1738          let block = sample_next_block(&vm, &private_key, &[transaction, adjusted_transaction.clone()], rng).unwrap();
1739  
1740          // Check that the block aborts the deployment transaction.
1741          assert_eq!(block.aborted_transaction_ids(), &vec![adjusted_transaction.id()]);
1742  
1743          // Update the VM.
1744          vm.add_next_block(&block).unwrap();
1745      }
1746  
1747      #[test]
1748      fn test_deployment_variable_underreport() {
1749          let rng = &mut TestRng::default();
1750  
1751          // Initialize a private key.
1752          let private_key = sample_genesis_private_key(rng);
1753          let address = Address::try_from(&private_key).unwrap();
1754  
1755          // Initialize the genesis block.
1756          let genesis = sample_genesis_block(rng);
1757  
1758          // Initialize the VM.
1759          let vm = sample_vm();
1760          // Update the VM.
1761          vm.add_next_block(&genesis).unwrap();
1762  
1763          // Deploy the base program.
1764          let program = Program::from_str(
1765              r"
1766  program synthesis_underreport.alpha;
1767  function do:
1768      input r0 as u32.private;
1769      add r0 r0 into r1;
1770      output r1 as u32.public;",
1771          )
1772          .unwrap();
1773  
1774          // Create the deployment transaction.
1775          let transaction = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1776  
1777          // Destructure the deployment transaction.
1778          let Transaction::Deploy(txid, _, program_owner, deployment, fee) = transaction else {
1779              panic!("Expected a deployment transaction");
1780          };
1781  
1782          // Decrease the number of reported variables in the verifying keys.
1783          let mut vks_with_underreport = Vec::with_capacity(deployment.verifying_keys().len());
1784          for (id, (vk, cert)) in deployment.verifying_keys() {
1785              let vk = VerifyingKey::new(Arc::new(vk.deref().clone()), vk.num_variables() - 2);
1786              vks_with_underreport.push((*id, (vk.clone(), cert.clone())));
1787          }
1788  
1789          // Create a new deployment transaction with the underreported verifying keys.
1790          let adjusted_deployment = Deployment::new(
1791              deployment.edition(),
1792              deployment.program().clone(),
1793              vks_with_underreport,
1794              deployment.program_checksum(),
1795              deployment.program_owner(),
1796          )
1797          .unwrap();
1798          let deployment_id = adjusted_deployment.to_deployment_id().unwrap();
1799          let adjusted_transaction =
1800              Transaction::Deploy(txid, deployment_id, program_owner, Box::new(adjusted_deployment), fee);
1801  
1802          // Verify the deployment transaction. It should error when synthesizing the first variable over the vk limit.
1803          let result = vm.check_transaction(&adjusted_transaction, None, rng);
1804          assert!(result.is_err());
1805  
1806          // Create a standard transaction
1807          // Prepare the inputs.
1808          let inputs = [
1809              Value::<CurrentNetwork>::from_str(&address.to_string()).unwrap(),
1810              Value::<CurrentNetwork>::from_str("1u64").unwrap(),
1811          ]
1812          .into_iter();
1813  
1814          // Execute.
1815          let transaction =
1816              vm.execute(&private_key, ("credits.alpha", "transfer_public"), inputs, None, 0, None, rng).unwrap();
1817  
1818          // Check that the deployment transaction will be aborted if injected into a block.
1819          let block = sample_next_block(&vm, &private_key, &[transaction, adjusted_transaction.clone()], rng).unwrap();
1820  
1821          // Check that the block aborts the deployment transaction.
1822          assert_eq!(block.aborted_transaction_ids(), &vec![adjusted_transaction.id()]);
1823  
1824          // Update the VM.
1825          vm.add_next_block(&block).unwrap();
1826      }
1827  
1828      #[test]
1829      #[ignore]
1830      fn test_deployment_memory_overload() {
1831          const NUM_DEPLOYMENTS: usize = 32;
1832  
1833          let rng = &mut TestRng::default();
1834  
1835          // Initialize a private key.
1836          let private_key = sample_genesis_private_key(rng);
1837  
1838          // Initialize a view key.
1839          let view_key = ViewKey::try_from(&private_key).unwrap();
1840  
1841          // Initialize the genesis block.
1842          let genesis = sample_genesis_block(rng);
1843  
1844          // Initialize the VM.
1845          let vm = sample_vm();
1846          // Update the VM.
1847          vm.add_next_block(&genesis).unwrap();
1848  
1849          // Deploy the base program.
1850          let program = Program::from_str(
1851              r"
1852  program program_layer_0.alpha;
1853  
1854  mapping m:
1855      key as u8.public;
1856      value as u32.public;
1857  
1858  function do:
1859      input r0 as u32.public;
1860      async do r0 into r1;
1861      output r1 as program_layer_0.alpha/do.future;
1862  
1863  finalize do:
1864      input r0 as u32.public;
1865      set r0 into m[0u8];",
1866          )
1867          .unwrap();
1868  
1869          let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1870          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
1871  
1872          // For each layer, deploy a program that calls the program from the previous layer.
1873          for i in 1..NUM_DEPLOYMENTS {
1874              let mut program_string = String::new();
1875              // Add the import statements.
1876              for j in 0..i {
1877                  program_string.push_str(&format!("import program_layer_{j}.alpha;\n"));
1878              }
1879              // Add the program body.
1880              program_string.push_str(&format!(
1881                  "program program_layer_{i}.alpha;
1882  
1883  mapping m:
1884      key as u8.public;
1885      value as u32.public;
1886  
1887  function do:
1888      input r0 as u32.public;
1889      call program_layer_{prev}.alpha/do r0 into r1;
1890      async do r0 r1 into r2;
1891      output r2 as program_layer_{i}.alpha/do.future;
1892  
1893  finalize do:
1894      input r0 as u32.public;
1895      input r1 as program_layer_{prev}.alpha/do.future;
1896      await r1;
1897      set r0 into m[0u8];",
1898                  prev = i - 1
1899              ));
1900              // Construct the program.
1901              let program = Program::from_str(&program_string).unwrap();
1902  
1903              // Deploy the program.
1904              let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap();
1905  
1906              vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
1907          }
1908  
1909          // Fetch the unspent records.
1910          let records = genesis.transitions().cloned().flat_map(Transition::into_records).collect::<IndexMap<_, _>>();
1911          trace!("Unspent Records:\n{:#?}", records);
1912  
1913          // Select a record to spend.
1914          let record = Some(records.values().next().unwrap().decrypt(&view_key).unwrap());
1915  
1916          // Prepare the inputs.
1917          let inputs = [Value::<CurrentNetwork>::from_str("1u32").unwrap()].into_iter();
1918  
1919          // Execute.
1920          let transaction =
1921              vm.execute(&private_key, ("program_layer_30.alpha", "do"), inputs, record, 0, None, rng).unwrap();
1922  
1923          // Verify.
1924          vm.check_transaction(&transaction, None, rng).unwrap();
1925      }
1926  
1927      #[test]
1928      fn test_transfer_public_from_user() {
1929          let rng = &mut TestRng::default();
1930  
1931          // Initialize a new caller.
1932          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
1933          let caller_address = Address::try_from(&caller_private_key).unwrap();
1934  
1935          // Initialize a recipient.
1936          let recipient_private_key = PrivateKey::new(rng).unwrap();
1937          let recipient_address = Address::try_from(&recipient_private_key).unwrap();
1938  
1939          // Initialize the genesis block.
1940          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
1941  
1942          // Initialize the VM.
1943          let vm = crate::vm::test_helpers::sample_vm();
1944  
1945          // Update the VM.
1946          vm.add_next_block(&genesis).unwrap();
1947  
1948          // Check the balance of the caller.
1949          let credits_program_id = ProgramID::from_str("credits.alpha").unwrap();
1950          let account_mapping_name = Identifier::from_str("account").unwrap();
1951          let balance = match vm
1952              .finalize_store()
1953              .get_value_confirmed(
1954                  credits_program_id,
1955                  account_mapping_name,
1956                  &Plaintext::from(Literal::Address(caller_address)),
1957              )
1958              .unwrap()
1959          {
1960              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
1961              _ => panic!("Expected a valid balance"),
1962          };
1963          assert_eq!(balance, 182_499_999_894_112, "Update me if the initial balance changes.");
1964  
1965          // Transfer credits from the caller to the recipient.
1966          let transaction = vm
1967              .execute(
1968                  &caller_private_key,
1969                  ("credits.alpha", "transfer_public"),
1970                  [Value::from_str(&format!("{recipient_address}")).unwrap(), Value::from_str("1u64").unwrap()].iter(),
1971                  None,
1972                  0,
1973                  None,
1974                  rng,
1975              )
1976              .unwrap();
1977  
1978          // Verify the transaction.
1979          vm.check_transaction(&transaction, None, rng).unwrap();
1980  
1981          // Add the transaction to a block and update the VM.
1982          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
1983  
1984          // Update the VM.
1985          vm.add_next_block(&block).unwrap();
1986  
1987          // Check the balance of the caller.
1988          let balance = match vm
1989              .finalize_store()
1990              .get_value_confirmed(
1991                  credits_program_id,
1992                  account_mapping_name,
1993                  &Plaintext::from(Literal::Address(caller_address)),
1994              )
1995              .unwrap()
1996          {
1997              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
1998              _ => panic!("Expected a valid balance"),
1999          };
2000          assert_eq!(balance, 182_499_999_843_051, "Update me if the initial balance changes.");
2001  
2002          // Check the balance of the recipient.
2003          let balance = match vm
2004              .finalize_store()
2005              .get_value_confirmed(
2006                  credits_program_id,
2007                  account_mapping_name,
2008                  &Plaintext::from(Literal::Address(recipient_address)),
2009              )
2010              .unwrap()
2011          {
2012              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2013              _ => panic!("Expected a valid balance"),
2014          };
2015          assert_eq!(balance, 1, "Update me if the test amount changes.");
2016      }
2017  
2018      #[test]
2019      fn test_transfer_public_as_signer_from_user() {
2020          let rng = &mut TestRng::default();
2021  
2022          // Initialize a new caller.
2023          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
2024          let caller_address = Address::try_from(&caller_private_key).unwrap();
2025  
2026          // Initialize a recipient.
2027          let recipient_private_key = PrivateKey::new(rng).unwrap();
2028          let recipient_address = Address::try_from(&recipient_private_key).unwrap();
2029  
2030          // Initialize the genesis block.
2031          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
2032  
2033          // Initialize the VM.
2034          let vm = crate::vm::test_helpers::sample_vm();
2035  
2036          // Update the VM.
2037          vm.add_next_block(&genesis).unwrap();
2038  
2039          // Check the balance of the caller.
2040          let credits_program_id = ProgramID::from_str("credits.alpha").unwrap();
2041          let account_mapping_name = Identifier::from_str("account").unwrap();
2042          let balance = match vm
2043              .finalize_store()
2044              .get_value_confirmed(
2045                  credits_program_id,
2046                  account_mapping_name,
2047                  &Plaintext::from(Literal::Address(caller_address)),
2048              )
2049              .unwrap()
2050          {
2051              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2052              _ => panic!("Expected a valid balance"),
2053          };
2054          assert_eq!(balance, 182_499_999_894_112, "Update me if the initial balance changes.");
2055  
2056          // Transfer credits from the caller to the recipient.
2057          let transaction = vm
2058              .execute(
2059                  &caller_private_key,
2060                  ("credits.alpha", "transfer_public_as_signer"),
2061                  [Value::from_str(&format!("{recipient_address}")).unwrap(), Value::from_str("1u64").unwrap()].iter(),
2062                  None,
2063                  0,
2064                  None,
2065                  rng,
2066              )
2067              .unwrap();
2068  
2069          // Verify the transaction.
2070          vm.check_transaction(&transaction, None, rng).unwrap();
2071  
2072          // Add the transaction to a block and update the VM.
2073          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
2074  
2075          // Update the VM.
2076          vm.add_next_block(&block).unwrap();
2077  
2078          // Check the balance of the caller.
2079          let balance = match vm
2080              .finalize_store()
2081              .get_value_confirmed(
2082                  credits_program_id,
2083                  account_mapping_name,
2084                  &Plaintext::from(Literal::Address(caller_address)),
2085              )
2086              .unwrap()
2087          {
2088              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2089              _ => panic!("Expected a valid balance"),
2090          };
2091          assert_eq!(balance, 182_499_999_843_031, "Update me if the initial balance changes.");
2092  
2093          // Check the balance of the recipient.
2094          let balance = match vm
2095              .finalize_store()
2096              .get_value_confirmed(
2097                  credits_program_id,
2098                  account_mapping_name,
2099                  &Plaintext::from(Literal::Address(recipient_address)),
2100              )
2101              .unwrap()
2102          {
2103              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2104              _ => panic!("Expected a valid balance"),
2105          };
2106          assert_eq!(balance, 1, "Update me if the test amount changes.");
2107      }
2108  
2109      #[test]
2110      fn transfer_public_from_program() {
2111          let rng = &mut TestRng::default();
2112  
2113          // Initialize a new caller.
2114          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
2115          let caller_address = Address::try_from(&caller_private_key).unwrap();
2116  
2117          // Initialize a recipient.
2118          let recipient_private_key = PrivateKey::new(rng).unwrap();
2119          let recipient_address = Address::try_from(&recipient_private_key).unwrap();
2120  
2121          // Initialize the genesis block.
2122          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
2123  
2124          // Initialize the VM.
2125          let vm = crate::vm::test_helpers::sample_vm();
2126  
2127          // Update the VM.
2128          vm.add_next_block(&genesis).unwrap();
2129  
2130          // Check the balance of the caller.
2131          let credits_program_id = ProgramID::from_str("credits.alpha").unwrap();
2132          let account_mapping_name = Identifier::from_str("account").unwrap();
2133          let balance = match vm
2134              .finalize_store()
2135              .get_value_confirmed(
2136                  credits_program_id,
2137                  account_mapping_name,
2138                  &Plaintext::from(Literal::Address(caller_address)),
2139              )
2140              .unwrap()
2141          {
2142              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2143              _ => panic!("Expected a valid balance"),
2144          };
2145          assert_eq!(balance, 182_499_999_894_112, "Update me if the initial balance changes.");
2146  
2147          // Initialize a wrapper program, importing `credits.alpha` and calling `transfer_public`.
2148          let program = Program::from_str(
2149              r"
2150  import credits.alpha;
2151  program credits_wrapper.alpha;
2152  
2153  function transfer_public:
2154      input r0 as address.public;
2155      input r1 as u64.public;
2156      call credits.alpha/transfer_public r0 r1 into r2;
2157      async transfer_public r2 into r3;
2158      output r3 as credits_wrapper.alpha/transfer_public.future;
2159  
2160  finalize transfer_public:
2161      input r0 as credits.alpha/transfer_public.future;
2162      await r0;
2163          ",
2164          )
2165          .unwrap();
2166  
2167          // Get the address of the wrapper program.
2168          let wrapper_program_id = ProgramID::from_str("credits_wrapper.alpha").unwrap();
2169          let wrapper_program_address = wrapper_program_id.to_address().unwrap();
2170  
2171          // Deploy the wrapper program.
2172          let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
2173  
2174          // Add the deployment to a block and update the VM.
2175          let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
2176  
2177          // Update the VM.
2178          vm.add_next_block(&block).unwrap();
2179  
2180          // Transfer credits from the caller to the `credits_wrapper` program.
2181          let transaction = vm
2182              .execute(
2183                  &caller_private_key,
2184                  ("credits.alpha", "transfer_public"),
2185                  [Value::from_str(&format!("{wrapper_program_address}")).unwrap(), Value::from_str("1u64").unwrap()]
2186                      .iter(),
2187                  None,
2188                  0,
2189                  None,
2190                  rng,
2191              )
2192              .unwrap();
2193  
2194          // Verify the transaction.
2195          vm.check_transaction(&transaction, None, rng).unwrap();
2196  
2197          // Add the transaction to a block and update the VM.
2198          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
2199  
2200          // Update the VM.
2201          vm.add_next_block(&block).unwrap();
2202  
2203          // Check the balance of the caller.
2204          let balance = match vm
2205              .finalize_store()
2206              .get_value_confirmed(
2207                  credits_program_id,
2208                  account_mapping_name,
2209                  &Plaintext::from(Literal::Address(caller_address)),
2210              )
2211              .unwrap()
2212          {
2213              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2214              _ => panic!("Expected a valid balance"),
2215          };
2216          assert_eq!(balance, 182_499_996_914_676, "Update me if the initial balance changes.");
2217  
2218          // Check the balance of the `credits_wrapper` program.
2219          let balance = match vm
2220              .finalize_store()
2221              .get_value_confirmed(
2222                  credits_program_id,
2223                  account_mapping_name,
2224                  &Plaintext::from(Literal::Address(wrapper_program_address)),
2225              )
2226              .unwrap()
2227          {
2228              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2229              _ => panic!("Expected a valid balance"),
2230          };
2231          assert_eq!(balance, 1, "Update me if the test amount changes.");
2232  
2233          // Transfer credits from the `credits_wrapper` program to the recipient.
2234          let transaction = vm
2235              .execute(
2236                  &caller_private_key,
2237                  ("credits_wrapper.alpha", "transfer_public"),
2238                  [Value::from_str(&format!("{recipient_address}")).unwrap(), Value::from_str("1u64").unwrap()].iter(),
2239                  None,
2240                  0,
2241                  None,
2242                  rng,
2243              )
2244              .unwrap();
2245  
2246          // Verify the transaction.
2247          vm.check_transaction(&transaction, None, rng).unwrap();
2248  
2249          // Add the transaction to a block and update the VM.
2250          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
2251  
2252          // Update the VM.
2253          vm.add_next_block(&block).unwrap();
2254  
2255          // Check the balance of the caller.
2256          let balance = match vm
2257              .finalize_store()
2258              .get_value_confirmed(
2259                  credits_program_id,
2260                  account_mapping_name,
2261                  &Plaintext::from(Literal::Address(caller_address)),
2262              )
2263              .unwrap()
2264          {
2265              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2266              _ => panic!("Expected a valid balance"),
2267          };
2268          assert_eq!(balance, 182_499_996_862_151, "Update me if the initial balance changes.");
2269  
2270          // Check the balance of the `credits_wrapper` program.
2271          let balance = match vm
2272              .finalize_store()
2273              .get_value_confirmed(
2274                  credits_program_id,
2275                  account_mapping_name,
2276                  &Plaintext::from(Literal::Address(wrapper_program_address)),
2277              )
2278              .unwrap()
2279          {
2280              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2281              _ => panic!("Expected a valid balance"),
2282          };
2283          assert_eq!(balance, 0);
2284  
2285          // Check the balance of the recipient.
2286          let balance = match vm
2287              .finalize_store()
2288              .get_value_confirmed(
2289                  credits_program_id,
2290                  account_mapping_name,
2291                  &Plaintext::from(Literal::Address(recipient_address)),
2292              )
2293              .unwrap()
2294          {
2295              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2296              _ => panic!("Expected a valid balance"),
2297          };
2298          assert_eq!(balance, 1, "Update me if the test amount changes.");
2299      }
2300  
2301      #[test]
2302      fn transfer_public_as_signer_from_program() {
2303          let rng = &mut TestRng::default();
2304  
2305          // Initialize a new caller.
2306          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
2307          let caller_address = Address::try_from(&caller_private_key).unwrap();
2308  
2309          // Initialize a recipient.
2310          let recipient_private_key = PrivateKey::new(rng).unwrap();
2311          let recipient_address = Address::try_from(&recipient_private_key).unwrap();
2312  
2313          // Initialize the genesis block.
2314          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
2315  
2316          // Initialize the VM.
2317          let vm = crate::vm::test_helpers::sample_vm();
2318  
2319          // Update the VM.
2320          vm.add_next_block(&genesis).unwrap();
2321  
2322          // Check the balance of the caller.
2323          let credits_program_id = ProgramID::from_str("credits.alpha").unwrap();
2324          let account_mapping_name = Identifier::from_str("account").unwrap();
2325          let balance = match vm
2326              .finalize_store()
2327              .get_value_confirmed(
2328                  credits_program_id,
2329                  account_mapping_name,
2330                  &Plaintext::from(Literal::Address(caller_address)),
2331              )
2332              .unwrap()
2333          {
2334              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2335              _ => panic!("Expected a valid balance"),
2336          };
2337          assert_eq!(balance, 182_499_999_894_112, "Update me if the initial balance changes.");
2338  
2339          // Initialize a wrapper program, importing `credits.alpha` and calling `transfer_public`.
2340          let program = Program::from_str(
2341              r"
2342  import credits.alpha;
2343  program credits_wrapper.alpha;
2344  
2345  function transfer_public_as_signer:
2346      input r0 as address.public;
2347      input r1 as u64.public;
2348      call credits.alpha/transfer_public_as_signer r0 r1 into r2;
2349      async transfer_public_as_signer r2 into r3;
2350      output r3 as credits_wrapper.alpha/transfer_public_as_signer.future;
2351  
2352  finalize transfer_public_as_signer:
2353      input r0 as credits.alpha/transfer_public_as_signer.future;
2354      await r0;
2355          ",
2356          )
2357          .unwrap();
2358  
2359          // Get the address of the wrapper program.
2360          let wrapper_program_id = ProgramID::from_str("credits_wrapper.alpha").unwrap();
2361          let wrapper_program_address = wrapper_program_id.to_address().unwrap();
2362  
2363          // Deploy the wrapper program.
2364          let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
2365  
2366          // Add the deployment to a block and update the VM.
2367          let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
2368  
2369          // Update the VM.
2370          vm.add_next_block(&block).unwrap();
2371  
2372          // Transfer credits from the signer using `credits_wrapper` program.
2373          let transaction = vm
2374              .execute(
2375                  &caller_private_key,
2376                  ("credits_wrapper.alpha", "transfer_public_as_signer"),
2377                  [Value::from_str(&format!("{recipient_address}")).unwrap(), Value::from_str("1u64").unwrap()].iter(),
2378                  None,
2379                  0,
2380                  None,
2381                  rng,
2382              )
2383              .unwrap();
2384  
2385          // Verify the transaction.
2386          vm.check_transaction(&transaction, None, rng).unwrap();
2387  
2388          // Add the transaction to a block and update the VM.
2389          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
2390  
2391          // Update the VM.
2392          vm.add_next_block(&block).unwrap();
2393  
2394          // Check the balance of the caller.
2395          let balance = match vm
2396              .finalize_store()
2397              .get_value_confirmed(
2398                  credits_program_id,
2399                  account_mapping_name,
2400                  &Plaintext::from(Literal::Address(caller_address)),
2401              )
2402              .unwrap()
2403          {
2404              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2405              _ => panic!("Expected a valid balance"),
2406          };
2407          assert_eq!(balance, 182_499_996_821_661, "Update me if the initial balance changes.");
2408  
2409          // Check the `credits_wrapper` program does not have any balance.
2410          let balance = vm
2411              .finalize_store()
2412              .get_value_confirmed(
2413                  credits_program_id,
2414                  account_mapping_name,
2415                  &Plaintext::from(Literal::Address(wrapper_program_address)),
2416              )
2417              .unwrap();
2418          assert!(balance.is_none());
2419  
2420          // Check the balance of the recipient.
2421          let balance = match vm
2422              .finalize_store()
2423              .get_value_confirmed(
2424                  credits_program_id,
2425                  account_mapping_name,
2426                  &Plaintext::from(Literal::Address(recipient_address)),
2427              )
2428              .unwrap()
2429          {
2430              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2431              _ => panic!("Expected a valid balance"),
2432          };
2433          assert_eq!(balance, 1, "Update me if the test amount changes.");
2434      }
2435  
2436      #[test]
2437      fn test_transfer_public_to_private_from_program() {
2438          let rng = &mut TestRng::default();
2439  
2440          // Initialize a new caller.
2441          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
2442          let caller_address = Address::try_from(&caller_private_key).unwrap();
2443  
2444          // Initialize a recipient.
2445          let recipient_private_key = PrivateKey::new(rng).unwrap();
2446          let recipient_address = Address::try_from(&recipient_private_key).unwrap();
2447  
2448          // Initialize the genesis block.
2449          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
2450  
2451          // Initialize the VM.
2452          let vm = crate::vm::test_helpers::sample_vm();
2453  
2454          // Update the VM.
2455          vm.add_next_block(&genesis).unwrap();
2456  
2457          // Check the balance of the caller.
2458          let credits_program_id = ProgramID::from_str("credits.alpha").unwrap();
2459          let account_mapping_name = Identifier::from_str("account").unwrap();
2460          let balance = match vm
2461              .finalize_store()
2462              .get_value_confirmed(
2463                  credits_program_id,
2464                  account_mapping_name,
2465                  &Plaintext::from(Literal::Address(caller_address)),
2466              )
2467              .unwrap()
2468          {
2469              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2470              _ => panic!("Expected a valid balance"),
2471          };
2472          assert_eq!(balance, 182_499_999_894_112, "Update me if the initial balance changes.");
2473  
2474          // Check that the recipient does not have a public balance.
2475          let balance = vm
2476              .finalize_store()
2477              .get_value_confirmed(
2478                  credits_program_id,
2479                  account_mapping_name,
2480                  &Plaintext::from(Literal::Address(recipient_address)),
2481              )
2482              .unwrap();
2483          assert!(balance.is_none());
2484  
2485          // Initialize a wrapper program, importing `credits.alpha` and calling `transfer_public_as_signer` then `transfer_public_to_private`.
2486          let program = Program::from_str(
2487              r"
2488  import credits.alpha;
2489  
2490  program credits_wrapper.alpha;
2491  
2492  function transfer_public_to_private:
2493      input r0 as address.private;
2494      input r1 as u64.public;
2495      call credits.alpha/transfer_public_as_signer credits_wrapper.alpha r1 into r2;
2496      call credits.alpha/transfer_public_to_private r0 r1 into r3 r4;
2497      async transfer_public_to_private r2 r4 into r5;
2498      output r3 as credits.alpha/credits.record;
2499      output r5 as credits_wrapper.alpha/transfer_public_to_private.future;
2500  
2501  finalize transfer_public_to_private:
2502      input r0 as credits.alpha/transfer_public_as_signer.future;
2503      input r1 as credits.alpha/transfer_public_to_private.future;
2504      contains credits.alpha/account[credits_wrapper.alpha] into r2;
2505      assert.eq r2 false;
2506      await r0;
2507      get credits.alpha/account[credits_wrapper.alpha] into r3;
2508      assert.eq r3 r0[2u32];
2509      await r1;
2510          ",
2511          )
2512          .unwrap();
2513  
2514          // Get the address of the wrapper program.
2515          let wrapper_program_id = ProgramID::from_str("credits_wrapper.alpha").unwrap();
2516  
2517          // Deploy the wrapper program.
2518          let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
2519  
2520          // Add the deployment to a block and update the VM.
2521          let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
2522  
2523          // Update the VM.
2524          vm.add_next_block(&block).unwrap();
2525  
2526          // Call the wrapper program to transfer credits from the caller to the recipient.
2527          let transaction = vm
2528              .execute(
2529                  &caller_private_key,
2530                  ("credits_wrapper.alpha", "transfer_public_to_private"),
2531                  [Value::from_str(&format!("{recipient_address}")).unwrap(), Value::from_str("1u64").unwrap()].iter(),
2532                  None,
2533                  0,
2534                  None,
2535                  rng,
2536              )
2537              .unwrap();
2538  
2539          // Verify the transaction.
2540          vm.check_transaction(&transaction, None, rng).unwrap();
2541  
2542          // Add the transaction to a block and update the VM.
2543          let block = sample_next_block(&vm, &caller_private_key, &[transaction.clone()], rng).unwrap();
2544  
2545          // Update the VM.
2546          vm.add_next_block(&block).unwrap();
2547  
2548          // Check the balance of the caller.
2549          let balance = match vm
2550              .finalize_store()
2551              .get_value_confirmed(
2552                  credits_program_id,
2553                  account_mapping_name,
2554                  &Plaintext::from(Literal::Address(caller_address)),
2555              )
2556              .unwrap()
2557          {
2558              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2559              _ => panic!("Expected a valid balance"),
2560          };
2561  
2562          assert_eq!(balance, 182_499_995_667_116, "Update me if the initial balance changes.");
2563  
2564          // Check that the `credits_wrapper` program has a balance of 0.
2565          let balance = match vm
2566              .finalize_store()
2567              .get_value_confirmed(
2568                  credits_program_id,
2569                  account_mapping_name,
2570                  &Plaintext::from(Literal::Address(wrapper_program_id.to_address().unwrap())),
2571              )
2572              .unwrap()
2573          {
2574              Some(Value::Plaintext(Plaintext::Literal(Literal::U64(balance), _))) => *balance,
2575              _ => panic!("Expected a valid balance"),
2576          };
2577          assert_eq!(balance, 0);
2578  
2579          // Check that the recipient does not have a public balance.
2580          let balance = vm
2581              .finalize_store()
2582              .get_value_confirmed(
2583                  credits_program_id,
2584                  account_mapping_name,
2585                  &Plaintext::from(Literal::Address(recipient_address)),
2586              )
2587              .unwrap();
2588          assert!(balance.is_none());
2589  
2590          // Get the output record from the transaction and check that it is well-formed.
2591          let records = transaction.records().collect_vec();
2592          assert_eq!(records.len(), 1);
2593          let (commitment, record) = records[0];
2594          let record = record.decrypt(&ViewKey::try_from(&recipient_private_key).unwrap()).unwrap();
2595          assert_eq!(**record.owner(), recipient_address);
2596          let data = record.data();
2597          assert_eq!(data.len(), 1);
2598          match data.get(&Identifier::from_str("microcredits").unwrap()) {
2599              Some(Entry::<CurrentNetwork, _>::Private(Plaintext::Literal(Literal::U64(value), _))) => {
2600                  assert_eq!(**value, 1)
2601              }
2602              _ => panic!("Incorrect record."),
2603          }
2604  
2605          // Check that the record exists in the VM.
2606          assert!(vm.transition_store().get_record(commitment).unwrap().is_some());
2607  
2608          // Check that the serial number of the record does not exist in the VM.
2609          assert!(
2610              !vm.transition_store()
2611                  .contains_serial_number(
2612                      &Record::<CurrentNetwork, Plaintext<CurrentNetwork>>::serial_number(
2613                          recipient_private_key,
2614                          *commitment
2615                      )
2616                      .unwrap()
2617                  )
2618                  .unwrap()
2619          );
2620      }
2621  
2622      #[test]
2623      fn test_modify_transaction_output() {
2624          let rng = &mut TestRng::default();
2625  
2626          // Initialize a new caller.
2627          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
2628  
2629          // Initialize the genesis block.
2630          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
2631  
2632          // Initialize the VM.
2633          let vm = crate::vm::test_helpers::sample_vm();
2634  
2635          // Update the VM.
2636          vm.add_next_block(&genesis).unwrap();
2637  
2638          // Initialize a new private key.
2639          let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
2640  
2641          // Call `transfer_public_to_private`.
2642          let inputs = [
2643              Value::from_str(&format!("{}", Address::try_from(&private_key).unwrap())).unwrap(),
2644              Value::from_str("1u64").unwrap(),
2645          ];
2646          let transaction = vm
2647              .execute(
2648                  &caller_private_key,
2649                  ("credits.alpha", "transfer_public_to_private"),
2650                  inputs.iter(),
2651                  None,
2652                  0u64,
2653                  None,
2654                  rng,
2655              )
2656              .unwrap();
2657  
2658          // Check that the transaction is valid.
2659          vm.check_transaction(&transaction, None, rng).unwrap();
2660  
2661          // Check that the transaction is as expected.
2662          let transaction_string = transaction.to_string();
2663          // Parse the transaction string as a JSON map.
2664          let transaction: serde_json::Map<String, serde_json::Value> =
2665              serde_json::from_str(&transaction_string).unwrap();
2666          // Get the execution.
2667          let execution = transaction.get("execution").unwrap();
2668          // Get the `transfer_public_to_private` transition.
2669          let transition = execution.get("transitions").unwrap().as_array().unwrap().first().unwrap();
2670          // Check that the transition is as expected.
2671          assert_eq!(transition.get("program").unwrap(), "credits.alpha");
2672          assert_eq!(transition.get("function").unwrap(), "transfer_public_to_private");
2673          // Get the transition outputs.
2674          let outputs = transition.get("outputs").unwrap().as_array().unwrap();
2675          // For any output that is a future, modify it to an external record.
2676          let new_outputs = outputs
2677              .iter()
2678              .map(|output| {
2679                  if output.get("type").unwrap() == "future" {
2680                      let id = output.get("id").unwrap().as_str().unwrap();
2681                      json!({
2682                          "type": "external_record",
2683                          "id": id
2684                      })
2685                  } else {
2686                      output.clone()
2687                  }
2688              })
2689              .collect::<Vec<_>>();
2690  
2691          // Compute the new transition ID.
2692          let inputs = transition
2693              .get("inputs")
2694              .unwrap()
2695              .as_array()
2696              .unwrap()
2697              .iter()
2698              .map(|value| {
2699                  let string = serde_json::to_string(value).unwrap();
2700                  Input::from_str(&string).unwrap()
2701              })
2702              .collect::<Vec<_>>();
2703          let outputs = new_outputs
2704              .iter()
2705              .map(|value| {
2706                  let string = serde_json::to_string(value).unwrap();
2707                  Output::from_str(&string).unwrap()
2708              })
2709              .collect();
2710          let tpk = Group::from_str(transition.get("tpk").unwrap().as_str().unwrap()).unwrap();
2711          let tcm = Field::from_str(transition.get("tcm").unwrap().as_str().unwrap()).unwrap();
2712          let scm = Field::from_str(transition.get("scm").unwrap().as_str().unwrap()).unwrap();
2713          let transition = Transition::<CurrentNetwork>::new(
2714              ProgramID::from_str("credits.alpha").unwrap(),
2715              Identifier::from_str("transfer_public_to_private").unwrap(),
2716              inputs,
2717              outputs,
2718              tpk,
2719              tcm,
2720              scm,
2721          )
2722          .unwrap();
2723  
2724          // Construct the new transaction.
2725          let mut new_transitions = vec![transition];
2726          new_transitions.extend(execution.get("transitions").unwrap().as_array().unwrap().iter().skip(1).map(|value| {
2727              let string = serde_json::to_string(value).unwrap();
2728              Transition::from_str(&string).unwrap()
2729          }));
2730          let global_state_root = <CurrentNetwork as Network>::StateRoot::from_str(
2731              execution.get("global_state_root").unwrap().as_str().unwrap(),
2732          )
2733          .unwrap();
2734          let proof = Proof::<CurrentNetwork>::from_str(execution.get("proof").unwrap().as_str().unwrap()).unwrap();
2735          let new_execution = Execution::from(new_transitions.into_iter(), global_state_root, Some(proof)).unwrap();
2736          let authorization = vm
2737              .authorize_fee_public(&caller_private_key, 10_000_000, 0, new_execution.to_execution_id().unwrap(), rng)
2738              .unwrap();
2739          let fee = vm.execute_fee_authorization(authorization, None, rng).unwrap();
2740          let new_transaction = Transaction::from_execution(new_execution, Some(fee)).unwrap();
2741  
2742          // Verify the new transaction.
2743          assert!(vm.check_transaction(&new_transaction, None, rng).is_err());
2744      }
2745  
2746      #[test]
2747      fn test_modify_fee() {
2748          let rng = &mut TestRng::default();
2749  
2750          // Initialize a new caller.
2751          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
2752  
2753          // Initialize the genesis block.
2754          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
2755  
2756          // Initialize the VM.
2757          let vm = crate::vm::test_helpers::sample_vm();
2758  
2759          // Update the VM.
2760          vm.add_next_block(&genesis).unwrap();
2761  
2762          // Initialize a new private key.
2763          let private_key = PrivateKey::<CurrentNetwork>::new(rng).unwrap();
2764  
2765          // Call `transfer_public_to_private`.
2766          let inputs = [
2767              Value::from_str(&format!("{}", Address::try_from(&private_key).unwrap())).unwrap(),
2768              Value::from_str("1u64").unwrap(),
2769          ];
2770          let transaction = vm
2771              .execute(
2772                  &caller_private_key,
2773                  ("credits.alpha", "transfer_public_to_private"),
2774                  inputs.iter(),
2775                  None,
2776                  0u64,
2777                  None,
2778                  rng,
2779              )
2780              .unwrap();
2781  
2782          // Check that the transaction is valid.
2783          vm.check_transaction(&transaction, None, rng).unwrap();
2784  
2785          // Check that the transaction is as expected.
2786          let transaction_string = transaction.to_string();
2787          // Parse the transaction string as a JSON map.
2788          let transaction: serde_json::Map<String, serde_json::Value> =
2789              serde_json::from_str(&transaction_string).unwrap();
2790          // Get the execution.
2791          let execution: Execution<CurrentNetwork> =
2792              serde_json::from_value(transaction.get("execution").unwrap().clone()).unwrap();
2793  
2794          // Get the fee.
2795          let fee = transaction.get("fee").unwrap().as_object().unwrap();
2796          // Get the transition
2797          let transition = fee.get("transition").unwrap().as_object().unwrap();
2798          // Check that the transition is as expected.
2799          assert_eq!(transition.get("program").unwrap(), "credits.alpha");
2800          assert_eq!(transition.get("function").unwrap(), "fee_public");
2801          // Get the transition outputs.
2802          let outputs = transition.get("outputs").unwrap().as_array().unwrap();
2803          // For any output that is a future, modify it to an external record.
2804          let new_outputs = outputs
2805              .iter()
2806              .map(|output| {
2807                  if output.get("type").unwrap() == "future" {
2808                      let id = output.get("id").unwrap().as_str().unwrap();
2809                      json!({
2810                          "type": "external_record",
2811                          "id": id
2812                      })
2813                  } else {
2814                      output.clone()
2815                  }
2816              })
2817              .collect::<Vec<_>>();
2818  
2819          // Compute the new transition ID.
2820          let inputs = transition
2821              .get("inputs")
2822              .unwrap()
2823              .as_array()
2824              .unwrap()
2825              .iter()
2826              .map(|value| {
2827                  let string = serde_json::to_string(value).unwrap();
2828                  Input::from_str(&string).unwrap()
2829              })
2830              .collect::<Vec<_>>();
2831          let outputs = new_outputs
2832              .iter()
2833              .map(|value| {
2834                  let string = serde_json::to_string(value).unwrap();
2835                  Output::from_str(&string).unwrap()
2836              })
2837              .collect();
2838          let tpk = Group::from_str(transition.get("tpk").unwrap().as_str().unwrap()).unwrap();
2839          let tcm = Field::from_str(transition.get("tcm").unwrap().as_str().unwrap()).unwrap();
2840          let scm = Field::from_str(transition.get("scm").unwrap().as_str().unwrap()).unwrap();
2841          // Construct the new transition.
2842          let transition = Transition::<CurrentNetwork>::new(
2843              ProgramID::from_str("credits.alpha").unwrap(),
2844              Identifier::from_str("fee_public").unwrap(),
2845              inputs,
2846              outputs,
2847              tpk,
2848              tcm,
2849              scm,
2850          )
2851          .unwrap();
2852          // Get the state root.
2853          let global_state_root =
2854              <CurrentNetwork as Network>::StateRoot::from_str(fee.get("global_state_root").unwrap().as_str().unwrap())
2855                  .unwrap();
2856          // Get the proof.
2857          let proof = Proof::<CurrentNetwork>::from_str(fee.get("proof").unwrap().as_str().unwrap()).unwrap();
2858          // Construct the new fee.
2859          let fee = Fee::from(transition, global_state_root, Some(proof)).unwrap();
2860  
2861          // Construct the new transaction.
2862          let new_transaction = Transaction::from_execution(execution, Some(fee)).unwrap();
2863  
2864          // Verify the new transaction.
2865          assert!(vm.check_transaction(&new_transaction, None, rng).is_err());
2866      }
2867  
2868      #[test]
2869      fn test_modify_input_and_output() {
2870          let rng = &mut TestRng::default();
2871  
2872          // Initialize a new caller.
2873          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
2874  
2875          // Initialize the genesis block.
2876          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
2877  
2878          // Initialize the VM.
2879          let vm = crate::vm::test_helpers::sample_vm();
2880  
2881          // Update the VM.
2882          vm.add_next_block(&genesis).unwrap();
2883  
2884          // Deploy the test program.
2885          let program = Program::from_str(
2886              r"
2887  program basic_math.alpha;
2888  
2889  function add_thrice:
2890      input r0 as u64.public;
2891      input r1 as u64.private;
2892      add r0 r1 into r2;
2893      add r2 r1 into r3;
2894      add r3 r1 into r4;
2895      output r2 as u64.constant;
2896      output r3 as u64.public;
2897      output r4 as u64.private;
2898          ",
2899          )
2900          .unwrap();
2901          let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
2902          let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
2903          vm.add_next_block(&block).unwrap();
2904  
2905          // Call the test program.
2906          let transaction = vm
2907              .execute(
2908                  &caller_private_key,
2909                  ("basic_math.alpha", "add_thrice"),
2910                  [Value::from_str("1u64").unwrap(), Value::from_str("2u64").unwrap()].iter(),
2911                  None,
2912                  0u64,
2913                  None,
2914                  rng,
2915              )
2916              .unwrap();
2917  
2918          // Check that the transaction is valid.
2919          vm.check_transaction(&transaction, None, rng).unwrap();
2920  
2921          // Get the transaction string.
2922          let transaction_string = transaction.to_string();
2923          // Parse the transaction string as a JSON map.
2924          let transaction: serde_json::Map<String, serde_json::Value> =
2925              serde_json::from_str(&transaction_string).unwrap();
2926          // Get the execution.
2927          let execution = transaction.get("execution").unwrap();
2928          // Get the `add_twice` transition.
2929          let transition = execution.get("transitions").unwrap().as_array().unwrap().first().unwrap();
2930          // Get the transition inputs.
2931          let inputs = transition.get("inputs").unwrap().as_array().unwrap();
2932          // For any input, modify it to an external record.
2933          let new_inputs = inputs
2934              .iter()
2935              .map(|input| {
2936                  let id = input.get("id").unwrap().as_str().unwrap();
2937                  json!({
2938                      "type": "external_record",
2939                      "id": id
2940                  })
2941              })
2942              .collect::<Vec<_>>();
2943          // Get the transition outputs.
2944          let outputs = transition.get("outputs").unwrap().as_array().unwrap();
2945          // For any output, modify it to an external record.
2946          let new_outputs = outputs
2947              .iter()
2948              .map(|output| {
2949                  let id = output.get("id").unwrap().as_str().unwrap();
2950                  json!({
2951                      "type": "external_record",
2952                      "id": id
2953                  })
2954              })
2955              .collect::<Vec<_>>();
2956  
2957          // Compute the new transition ID.
2958          let inputs = new_inputs
2959              .iter()
2960              .map(|value| {
2961                  let string = serde_json::to_string(value).unwrap();
2962                  Input::from_str(&string).unwrap()
2963              })
2964              .collect::<Vec<_>>();
2965          let outputs = new_outputs
2966              .iter()
2967              .map(|value| {
2968                  let string = serde_json::to_string(value).unwrap();
2969                  Output::from_str(&string).unwrap()
2970              })
2971              .collect();
2972          let tpk = Group::from_str(transition.get("tpk").unwrap().as_str().unwrap()).unwrap();
2973          let tcm = Field::from_str(transition.get("tcm").unwrap().as_str().unwrap()).unwrap();
2974          let scm = Field::from_str(transition.get("scm").unwrap().as_str().unwrap()).unwrap();
2975  
2976          // Construct the new transition.
2977          let transition = Transition::<CurrentNetwork>::new(
2978              ProgramID::from_str("basic_math.alpha").unwrap(),
2979              Identifier::from_str("add_thrice").unwrap(),
2980              inputs,
2981              outputs,
2982              tpk,
2983              tcm,
2984              scm,
2985          )
2986          .unwrap();
2987  
2988          // Construct the new transaction.
2989          let mut new_transitions = vec![transition];
2990          new_transitions.extend(execution.get("transitions").unwrap().as_array().unwrap().iter().skip(1).map(|value| {
2991              let string = serde_json::to_string(value).unwrap();
2992              Transition::from_str(&string).unwrap()
2993          }));
2994          let global_state_root = <CurrentNetwork as Network>::StateRoot::from_str(
2995              execution.get("global_state_root").unwrap().as_str().unwrap(),
2996          )
2997          .unwrap();
2998          let proof = Proof::<CurrentNetwork>::from_str(execution.get("proof").unwrap().as_str().unwrap()).unwrap();
2999          let new_execution = Execution::from(new_transitions.into_iter(), global_state_root, Some(proof)).unwrap();
3000          let authorization = vm
3001              .authorize_fee_public(&caller_private_key, 10_000_000, 0, new_execution.to_execution_id().unwrap(), rng)
3002              .unwrap();
3003          let fee = vm.execute_fee_authorization(authorization, None, rng).unwrap();
3004          let new_transaction = Transaction::from_execution(new_execution, Some(fee)).unwrap();
3005  
3006          // Verify the new transaction.
3007          assert!(vm.check_transaction(&new_transaction, None, rng).is_err());
3008      }
3009  
3010      #[test]
3011      fn test_large_transaction_is_aborted() {
3012          let rng = &mut TestRng::default();
3013  
3014          // Initialize a new caller.
3015          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
3016  
3017          // Initialize the genesis block.
3018          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
3019  
3020          // Initialize the VM.
3021          let vm = crate::vm::test_helpers::sample_vm();
3022  
3023          // Update the VM.
3024          vm.add_next_block(&genesis).unwrap();
3025  
3026          // Deploy a program that produces small transactions.
3027          let program = small_transaction_program();
3028  
3029          // Deploy the program.
3030          let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
3031  
3032          // Add the deployment to a block and update the VM.
3033          let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
3034  
3035          // Update the VM.
3036          vm.add_next_block(&block).unwrap();
3037  
3038          // Deploy a program that produces large transactions.
3039          let program = large_transaction_program();
3040  
3041          // Deploy the program.
3042          let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
3043  
3044          // Add the deployment to a block and update the VM.
3045          let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
3046  
3047          // Update the VM.
3048          vm.add_next_block(&block).unwrap();
3049  
3050          // Call the program to produce the small transaction.
3051          let transaction = vm
3052              .execute(
3053                  &caller_private_key,
3054                  ("testing_small.alpha", "small_transaction"),
3055                  Vec::<Value<CurrentNetwork>>::new().iter(),
3056                  None,
3057                  0,
3058                  None,
3059                  rng,
3060              )
3061              .unwrap();
3062  
3063          // Verify the transaction.
3064          vm.check_transaction(&transaction, None, rng).unwrap();
3065  
3066          // Add the transaction to a block and update the VM.
3067          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
3068  
3069          // Check that the transaction was accepted.
3070          assert_eq!(block.transactions().num_accepted(), 1);
3071  
3072          // Update the VM.
3073          vm.add_next_block(&block).unwrap();
3074  
3075          // Call the program to produce a large transaction.
3076          let transaction = vm
3077              .execute(
3078                  &caller_private_key,
3079                  ("testing_large.alpha", "large_transaction"),
3080                  Vec::<Value<CurrentNetwork>>::new().iter(),
3081                  None,
3082                  0,
3083                  None,
3084                  rng,
3085              )
3086              .unwrap();
3087  
3088          // Verify that the transaction is invalid.
3089          assert!(vm.check_transaction(&transaction, None, rng).is_err());
3090  
3091          // Add the transaction to a block and update the VM.
3092          let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
3093  
3094          // Check that the transaction was aborted.
3095          assert_eq!(block.aborted_transaction_ids().len(), 1);
3096  
3097          // Update the VM.
3098          vm.add_next_block(&block).unwrap();
3099      }
3100  
3101      #[test]
3102      fn test_vm_puzzle() {
3103          // Attention: This test is used to ensure that the VM has performed downcasting correctly for
3104          // the puzzle, and that the underlying traits in the puzzle are working correctly. Please
3105          // *do not delete* this test as it is a critical safety check for the integrity of the
3106          // instantiation of the puzzle in the VM.
3107  
3108          let rng = &mut TestRng::default();
3109  
3110          // Initialize the VM.
3111          let vm = sample_vm();
3112  
3113          // Ensure this call succeeds.
3114          vm.puzzle.prove(rng.r#gen(), rng.r#gen(), rng.r#gen(), None).unwrap();
3115      }
3116  
3117      #[test]
3118      fn test_multi_transition_authorization_deserialization() {
3119          let rng = &mut TestRng::default();
3120  
3121          // Initialize a private key.
3122          let private_key = sample_genesis_private_key(rng);
3123  
3124          // Initialize the genesis block.
3125          let genesis = sample_genesis_block(rng);
3126  
3127          // Initialize the VM.
3128          let vm = sample_vm();
3129          // Update the VM.
3130          vm.add_next_block(&genesis).unwrap();
3131  
3132          // Deploy the base program.
3133          let child_program_1 = Program::from_str(
3134              r"
3135  program child_program_1.alpha;
3136  
3137  function check:
3138      input r0 as field.private;
3139      assert.eq r0 123456789123456789123456789123456789123456789123456789field;
3140          ",
3141          )
3142          .unwrap();
3143  
3144          let child_program_2 = Program::from_str(
3145              r"
3146  program child_program_2.alpha;
3147  
3148  function check:
3149      input r0 as field.private;
3150      assert.eq r0 123456789123456789123456789123456789123456789123456789field;
3151          ",
3152          )
3153          .unwrap();
3154  
3155          // Deploy the child programs and add them to a block
3156          let deployment_1 = vm.deploy(&private_key, &child_program_1, None, 0, None, rng).unwrap();
3157          assert!(vm.check_transaction(&deployment_1, None, rng).is_ok());
3158          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment_1], rng).unwrap()).unwrap();
3159  
3160          let deployment_2 = vm.deploy(&private_key, &child_program_2, None, 0, None, rng).unwrap();
3161          assert!(vm.check_transaction(&deployment_2, None, rng).is_ok());
3162          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment_2], rng).unwrap()).unwrap();
3163  
3164          // Check that child programs are deployed
3165          assert!(vm.contains_program(&ProgramID::from_str("child_program_1.alpha").unwrap()));
3166          assert!(vm.contains_program(&ProgramID::from_str("child_program_2.alpha").unwrap()));
3167  
3168          // Deploy the program that calls the program from the previous layer.
3169          let parent_program = Program::from_str(
3170              r"
3171  import child_program_1.alpha;
3172  import child_program_2.alpha;
3173  
3174  program parent_program.alpha;
3175  
3176  function check:
3177      input r0 as field.private;
3178      call child_program_1.alpha/check r0;
3179      call child_program_2.alpha/check r0;
3180          ",
3181          )
3182          .unwrap();
3183  
3184          let deployment = vm.deploy(&private_key, &parent_program, None, 0, None, rng).unwrap();
3185          assert!(vm.check_transaction(&deployment, None, rng).is_ok());
3186          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
3187  
3188          // Check that program is deployed.
3189          assert!(vm.contains_program(&ProgramID::from_str("parent_program.alpha").unwrap()));
3190  
3191          // Deploy the program that calls the program from the previous layer.
3192          let grandparent_program = Program::from_str(
3193              r"
3194  import parent_program.alpha;
3195  
3196  program grandparent_program.alpha;
3197  
3198  function check:
3199      input r0 as field.private;
3200      call parent_program.alpha/check r0;
3201      call parent_program.alpha/check r0;
3202      call parent_program.alpha/check r0;
3203          ",
3204          )
3205          .unwrap();
3206  
3207          let deployment = vm.deploy(&private_key, &grandparent_program, None, 0, None, rng).unwrap();
3208          assert!(vm.check_transaction(&deployment, None, rng).is_ok());
3209          vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap();
3210  
3211          // Check that program is deployed.
3212          assert!(vm.contains_program(&ProgramID::from_str("grandparent_program.alpha").unwrap()));
3213  
3214          // Initialize the process.
3215          let mut process = Process::<CurrentNetwork>::load().unwrap();
3216  
3217          // Load the child and parent program
3218          process.add_program(&child_program_1).unwrap();
3219          process.add_program(&child_program_2).unwrap();
3220          process.add_program(&parent_program).unwrap();
3221          process.add_program(&grandparent_program).unwrap();
3222  
3223          // Specify the function name on the parent program
3224          let function_name = Identifier::<CurrentNetwork>::from_str("check").unwrap();
3225  
3226          // Generate a random Field for input
3227          let input =
3228              Value::<CurrentNetwork>::from_str("123456789123456789123456789123456789123456789123456789field").unwrap();
3229  
3230          // Generate the authorization that will contain multiple transitions
3231          let authorization = process
3232              .authorize::<CurrentAleo, _>(
3233                  &private_key,
3234                  grandparent_program.id(),
3235                  &function_name,
3236                  vec![input].iter(),
3237                  rng,
3238              )
3239              .unwrap();
3240  
3241          // Assert the Authorization has more than 1 transitions
3242          assert!(authorization.transitions().len() > 1);
3243  
3244          // Serialize the Authorization into a String
3245          let authorization_serialized = authorization.to_string();
3246  
3247          // Attempt to deserialize the Authorization from String
3248          let deserialization_result = Authorization::<CurrentNetwork>::from_str(&authorization_serialized);
3249  
3250          // Assert that the deserialization result is Ok
3251          assert!(deserialization_result.is_ok());
3252      }
3253  
3254      #[cfg(feature = "rocks")]
3255      #[test]
3256      fn test_atomic_unpause_on_error() {
3257          let rng = &mut TestRng::default();
3258  
3259          // Initialize a genesis private key..
3260          let genesis_private_key = sample_genesis_private_key(rng);
3261  
3262          // Initialize the genesis block.
3263          let genesis = sample_genesis_block(rng);
3264  
3265          // Initialize a VM and sample 2 blocks using it.
3266          let vm = sample_vm();
3267          vm.add_next_block(&genesis).unwrap();
3268          let block1 = sample_next_block(&vm, &genesis_private_key, &[], rng).unwrap();
3269          vm.add_next_block(&block1).unwrap();
3270          let block2 = sample_next_block(&vm, &genesis_private_key, &[], rng).unwrap();
3271  
3272          // Create a new, rocks-based VM shadowing the 1st one.
3273          let vm = sample_vm();
3274          vm.add_next_block(&genesis).unwrap();
3275          // This time, however, try to insert the 2nd block first, which fails due to height.
3276          assert!(vm.add_next_block(&block2).is_err());
3277  
3278          // It should still be possible to insert the 1st block afterwards.
3279          vm.add_next_block(&block1).unwrap();
3280      }
3281  
3282      #[test]
3283      fn test_dependent_deployments_in_same_block() {
3284          let rng = &mut TestRng::default();
3285  
3286          // Initialize a new caller.
3287          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
3288  
3289          // Initialize the genesis block.
3290          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
3291  
3292          // Initialize the VM.
3293          let vm = crate::vm::test_helpers::sample_vm();
3294          vm.add_next_block(&genesis).unwrap();
3295  
3296          // Fund two accounts to pay for the deployment.
3297          // This has to be done because only one deployment can be made per fee-paying address per block.
3298          let private_key_1 = PrivateKey::new(rng).unwrap();
3299          let private_key_2 = PrivateKey::new(rng).unwrap();
3300          let address_1 = Address::try_from(&private_key_1).unwrap();
3301          let address_2 = Address::try_from(&private_key_2).unwrap();
3302  
3303          let tx_1 = vm
3304              .execute(
3305                  &caller_private_key,
3306                  ("credits.alpha", "transfer_public"),
3307                  [Value::from_str(&format!("{address_1}")).unwrap(), Value::from_str("100000000u64").unwrap()].iter(),
3308                  None,
3309                  0,
3310                  None,
3311                  rng,
3312              )
3313              .unwrap();
3314          let tx_2 = vm
3315              .execute(
3316                  &caller_private_key,
3317                  ("credits.alpha", "transfer_public"),
3318                  [Value::from_str(&format!("{address_2}")).unwrap(), Value::from_str("100000000u64").unwrap()].iter(),
3319                  None,
3320                  0,
3321                  None,
3322                  rng,
3323              )
3324              .unwrap();
3325  
3326          let block = sample_next_block(&vm, &caller_private_key, &[tx_1, tx_2], rng).unwrap();
3327          assert_eq!(block.transactions().num_accepted(), 2);
3328          assert_eq!(block.transactions().num_rejected(), 0);
3329          assert_eq!(block.aborted_transaction_ids().len(), 0);
3330          vm.add_next_block(&block).unwrap();
3331  
3332          // Deploy two programs that depend on each other.
3333          let program_1 = Program::from_str(
3334              r"
3335  program child_program.alpha;
3336  
3337  function adder:
3338      input r0 as u64.public;
3339      input r1 as u64.public;
3340      add r0 r1 into r2;
3341      output r2 as u64.public;
3342          ",
3343          )
3344          .unwrap();
3345  
3346          let program_2 = Program::from_str(
3347              r"
3348  import child_program.alpha;
3349  
3350  program parent_program.alpha;
3351  
3352  function adder:
3353      input r0 as u64.public;
3354      input r1 as u64.public;
3355      call child_program.alpha/adder r0 r1 into r2;
3356      output r2 as u64.public;
3357          ",
3358          )
3359          .unwrap();
3360  
3361          // Initialize an "off-chain" VM to generate the deployments.
3362          let off_chain_vm = sample_vm();
3363          off_chain_vm.add_next_block(&genesis).unwrap();
3364          off_chain_vm.add_next_block(&block).unwrap();
3365          // Deploy the first program.
3366          let deployment_1 = off_chain_vm.deploy(&private_key_1, &program_1, None, 0, None, rng).unwrap();
3367          // Check that the account has enough to pay for the deployment.
3368          assert_eq!(*deployment_1.fee_amount().unwrap(), 2483025);
3369          // Add the first program to the off-chain VM.
3370          off_chain_vm.process().write().add_program(&program_1).unwrap();
3371          // Deploy the second program.
3372          let deployment_2 = off_chain_vm.deploy(&private_key_2, &program_2, None, 0, None, rng).unwrap();
3373          // Check that the account has enough to pay for the deployment.
3374          assert_eq!(*deployment_2.fee_amount().unwrap(), 2659575);
3375          // Drop the off-chain VM.
3376          drop(off_chain_vm);
3377  
3378          let block = sample_next_block(&vm, &caller_private_key, &[deployment_1, deployment_2], rng).unwrap();
3379          assert_eq!(block.transactions().num_accepted(), 1);
3380          assert_eq!(block.transactions().num_rejected(), 0);
3381          assert_eq!(block.aborted_transaction_ids().len(), 1);
3382          vm.add_next_block(&block).unwrap();
3383  
3384          // Check that only `child_program.alpha` is in the VM.
3385          assert!(vm.process().read().contains_program(&ProgramID::from_str("child_program.alpha").unwrap()));
3386      }
3387  
3388      #[cfg(feature = "test")]
3389      #[test]
3390      fn test_versioned_keyword_restrictions() {
3391          let rng = &mut TestRng::default();
3392  
3393          // Initialize a new caller.
3394          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
3395  
3396          // Initialize the VM at a specific height.
3397          // We subtract by 7 to deploy the 7 invalid programs.
3398          let vm = sample_vm_at_height(CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V6).unwrap() - 7, rng);
3399  
3400          // Define the invalid program bodies.
3401          let invalid_program_bodies = [
3402              "function constructor:",
3403              "function dummy:\nclosure constructor: input r0 as u8; assert.eq r0 0u8;",
3404              "function dummy:\nmapping constructor: key as boolean.public; value as boolean.public;",
3405              "function dummy:\nrecord constructor: owner as address.private;",
3406              "function dummy:\nrecord foo: owner as address.public; constructor as address.public;",
3407              "function dummy:\nstruct constructor: foo as address;",
3408              "function dummy:\nstruct foo: constructor as address;",
3409          ];
3410  
3411          println!("Current height: {}", vm.block_store().current_block_height());
3412  
3413          // Deploy a test program for each of the invalid program bodies.
3414          // They should all be accepted by the VM, because the restriction is not yet in place.
3415          for (i, body) in invalid_program_bodies.iter().enumerate() {
3416              println!("Deploying 'valid' test program {i}: {body}");
3417              let program = Program::from_str(&format!("program test_valid_{i}.alpha;\n{body}")).unwrap();
3418              let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
3419              let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
3420              assert_eq!(block.transactions().num_accepted(), 1);
3421              assert_eq!(block.transactions().num_rejected(), 0);
3422              assert_eq!(block.aborted_transaction_ids().len(), 0);
3423              vm.add_next_block(&block).unwrap();
3424          }
3425  
3426          println!("Current height: {}", vm.block_store().current_block_height());
3427  
3428          // Deploy a test program for each of the invalid program bodies.
3429          // Verify that `check_transaction` fails for each of them.
3430          for (i, body) in invalid_program_bodies.iter().enumerate() {
3431              println!("Deploying 'invalid' test program {i}: {body}");
3432              let program = Program::from_str(&format!("program test_invalid_{i}.alpha;\n{body}")).unwrap();
3433              let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
3434              if let Err(e) = vm.check_transaction(&deployment, None, rng) {
3435                  println!("Error: {e}");
3436              } else {
3437                  panic!("Expected an error, but the deployment was accepted.")
3438              }
3439          }
3440  
3441          // Attempt to deploy a program with the name `constructor`.
3442          // Verify that `check_transaction` fails.
3443          let program = Program::from_str(r"program constructor.alpha; function dummy:").unwrap();
3444          let deployment = vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
3445          if let Err(e) = vm.check_transaction(&deployment, None, rng) {
3446              println!("Error: {e}");
3447          } else {
3448              panic!("Expected an error, but the deployment was accepted.")
3449          }
3450      }
3451  
3452      #[cfg(feature = "test")]
3453      #[test]
3454      fn test_deploy_and_execute_in_same_block_fails() {
3455          let rng = &mut TestRng::default();
3456  
3457          // Initialize a new caller.
3458          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
3459  
3460          // Initialize the genesis block.
3461          let genesis = crate::vm::test_helpers::sample_genesis_block(rng);
3462  
3463          // Initialize the VM.
3464          let vm = crate::vm::test_helpers::sample_vm();
3465          vm.add_next_block(&genesis).unwrap();
3466  
3467          // Deploy and execute a program in the same block.
3468          let program = Program::from_str(
3469              r"
3470  program adder_program.alpha;
3471  function adder:
3472      input r0 as u64.public;
3473      input r1 as u64.public;
3474      add r0 r1 into r2;
3475      output r2 as u64.public;
3476          ",
3477          )
3478          .unwrap();
3479  
3480          // Initialize an "off-chain" VM to generate the deployment and execution.
3481          let off_chain_vm = sample_vm();
3482          off_chain_vm.add_next_block(&genesis).unwrap();
3483          // Deploy the program.
3484          let deployment = off_chain_vm.deploy(&caller_private_key, &program, None, 0, None, rng).unwrap();
3485          // Check that the account has enough to pay for the deployment.
3486          assert_eq!(*deployment.fee_amount().unwrap(), 2483025);
3487          // Add the program to the off-chain VM.
3488          off_chain_vm.process().write().add_program(&program).unwrap();
3489          // Execute the program.
3490          let transaction = off_chain_vm
3491              .execute(
3492                  &caller_private_key,
3493                  ("adder_program.alpha", "adder"),
3494                  [Value::from_str("1u64").unwrap(), Value::from_str("2u64").unwrap()].iter(),
3495                  None,
3496                  0,
3497                  None,
3498                  rng,
3499              )
3500              .unwrap();
3501          // Verify the transaction.
3502          off_chain_vm.check_transaction(&transaction, None, rng).unwrap();
3503          // Check that the account has enough to pay for the execution.
3504          assert_eq!(*transaction.fee_amount().unwrap(), 1283);
3505          // Drop the off-chain VM.
3506          drop(off_chain_vm);
3507  
3508          let block = sample_next_block(&vm, &caller_private_key, &[deployment, transaction], rng).unwrap();
3509          assert_eq!(block.transactions().num_accepted(), 1);
3510          assert_eq!(block.transactions().num_rejected(), 0);
3511          assert_eq!(block.aborted_transaction_ids().len(), 1);
3512          vm.add_next_block(&block).unwrap();
3513  
3514          // Check that the program was deployed.
3515          assert!(vm.process().read().contains_program(&ProgramID::from_str("adder_program.alpha").unwrap()));
3516      }
3517  
3518      #[cfg(feature = "test")]
3519      #[test]
3520      fn test_deploy_string() {
3521          let rng = &mut TestRng::default();
3522  
3523          // Initialize a new caller.
3524          let caller_private_key = crate::vm::test_helpers::sample_genesis_private_key(rng);
3525  
3526          // Initialize the VM at consensus version 11.
3527          let vm = crate::vm::test_helpers::sample_vm_at_height(
3528              CurrentNetwork::CONSENSUS_HEIGHT(ConsensusVersion::V11).unwrap(),
3529              rng,
3530          );
3531  
3532          // Deploy and execute a program in the same block.
3533          let program = |i: u32| {
3534              Program::from_str(&format!(
3535                  r#"
3536  program strings_{i}.alpha;
3537  
3538  mapping foo:
3539      key as string.public;
3540      value as string.public;
3541  
3542  mapping test:
3543      key as string.public;
3544      value as [boolean; 1u32].public;
3545  
3546  function dummy:
3547      input r0 as string.public;
3548      input r1 as string.private;
3549      input r2 as string.private;
3550      assert.eq "hello_friend" "hello_friend";
3551      assert.neq r1 r2;
3552      async dummy r0 r1 r2 into r3;
3553      hash.bhp256 "hello" into r4 as address;
3554      output r3 as strings_{i}.alpha/dummy.future;
3555  
3556  finalize dummy:
3557      input r0 as string.public;
3558      input r1 as string.public;
3559      input r2 as string.public;
3560      assert.eq "hello_friend" "hello_friend";
3561      assert.neq r1 r2;
3562      get.or_use foo[r1] r0 into r3;
3563      set r2 into foo[r1];
3564      set "test" into foo[r2];
3565      set r2 into foo[r2];
3566      get foo[r1] into r4;
3567      assert.neq r3 r4;
3568      assert.eq r2 r4;
3569      assert.neq r0 r4;
3570      get.or_use foo[r1] "hello" into r5;
3571  
3572  function dummy_with_array:
3573      input r0 as [string; 3u32].public;
3574      input r1 as [string; 4u32].private;
3575      async dummy_with_array r0 r1 "test" into r2;
3576      output r2 as strings_{i}.alpha/dummy_with_array.future;
3577  
3578  finalize dummy_with_array:
3579      input r0 as [string; 3u32].public;
3580      input r1 as [string; 4u32].public;
3581      input r2 as string.public;
3582      set r2 into foo[r2];
3583  
3584  constructor:
3585      assert.eq true true;
3586          "#
3587              ))
3588              .unwrap()
3589          };
3590  
3591          // Deploy the program.
3592          let _deployment = vm.deploy(&caller_private_key, &program(0), None, 0, None, rng).unwrap();
3593          // Check the deployment.
3594          // NOTE: this will only consistently pass if string sampling is updated.
3595          // vm.check_transaction(&deployment, None, rng).unwrap();
3596  
3597          // let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
3598          // assert_eq!(block.transactions().num_accepted(), 1);
3599          // assert_eq!(block.transactions().num_rejected(), 0);
3600          // assert_eq!(block.aborted_transaction_ids().len(), 0);
3601          // vm.add_next_block(&block).unwrap();
3602  
3603          // // Check that the program was deployed.
3604          // assert!(vm.process().read().contains_program(&ProgramID::from_str("strings_0.alpha").unwrap()));
3605  
3606          // let hello_literal = Literal::String(StringType::new("hello"));
3607          // let hello_friend_literal = Literal::String(StringType::new("hello_friend"));
3608          // let hello_friends_literal = Literal::String(StringType::new("hello_friends"));
3609  
3610          // // Execution test 1
3611          // let hello_friend_1 = Value::from(hello_friend_literal.clone());
3612          // let hello_friend_2 = Value::from(hello_friend_literal.clone());
3613          // let hello_friends = Value::from(hello_friends_literal.clone());
3614  
3615          // // Execute the program.
3616          // let transaction = vm
3617          //     .execute(
3618          //         &caller_private_key,
3619          //         ("strings_0.alpha", "dummy"),
3620          //         [hello_friend_1, hello_friend_2, hello_friends].iter(),
3621          //         None,
3622          //         0,
3623          //         None,
3624          //         rng,
3625          //     )
3626          //     .unwrap();
3627          // // Verify the transaction.
3628          // vm.check_transaction(&transaction, None, rng).unwrap();
3629  
3630          // let block = sample_next_block(&vm, &caller_private_key, &[transaction], rng).unwrap();
3631          // assert_eq!(block.transactions().num_accepted(), 1);
3632          // assert_eq!(block.transactions().num_rejected(), 0);
3633          // assert_eq!(block.aborted_transaction_ids().len(), 0);
3634          // vm.add_next_block(&block).unwrap();
3635  
3636          // // Execution test 2: change the public type
3637          // let hello = Value::from(hello_literal.clone());
3638          // let hello_friend = Value::from(hello_friend_literal.clone());
3639          // let hello_friends = Value::from(hello_friends_literal.clone());
3640  
3641          // // Execute the program.
3642          // let transaction = vm.execute(
3643          //     &caller_private_key,
3644          //     ("strings_0.alpha", "dummy"),
3645          //     [hello, hello_friend, hello_friends].iter(),
3646          //     None,
3647          //     0,
3648          //     None,
3649          //     rng,
3650          // );
3651          // assert!(transaction.is_err());
3652  
3653          // // Execution test 3: change the private type
3654          // let hello_friend_1 = Value::from(hello_friend_literal.clone());
3655          // let hello_friend_2 = Value::from(hello_friend_literal.clone());
3656          // let hello = Value::from(hello_literal.clone());
3657  
3658          // // Execute the program.
3659          // let transaction = vm.execute(
3660          //     &caller_private_key,
3661          //     ("strings_0.alpha", "dummy"),
3662          //     [hello_friend_1, hello_friend_2, hello].iter(),
3663          //     None,
3664          //     0,
3665          //     None,
3666          //     rng,
3667          // );
3668          // assert!(transaction.is_err());
3669  
3670          // // Deploy another program.
3671          // let deployment = vm.deploy(&caller_private_key, &program(1), None, 0, None, rng).unwrap();
3672          // // Check the deployment.
3673          // assert!(vm.check_transaction(&deployment, None, rng).is_err());
3674  
3675          // let block = sample_next_block(&vm, &caller_private_key, &[deployment], rng).unwrap();
3676          // assert_eq!(block.transactions().num_accepted(), 0);
3677          // assert_eq!(block.transactions().num_rejected(), 0);
3678          // assert_eq!(block.aborted_transaction_ids().len(), 1);
3679          // vm.add_next_block(&block).unwrap();
3680  
3681          // // Check that the program was notdeployed.
3682          // assert!(!vm.process().read().contains_program(&ProgramID::from_str("strings_1.alpha").unwrap()));
3683      }
3684  }