From 2482c9b2cc8a77c0985430aa2c1178aaa67e2d63 Mon Sep 17 00:00:00 2001 From: ljedrz Date: Thu, 22 Aug 2024 19:30:04 +0200 Subject: [PATCH 1/5] refactor: use explicit wrapping addition in Fp*::mul_assign Signed-off-by: ljedrz --- fields/src/fp_256.rs | 8 ++++---- fields/src/fp_384.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fields/src/fp_256.rs b/fields/src/fp_256.rs index 80f69a635b..bb70c0cc4f 100644 --- a/fields/src/fp_256.rs +++ b/fields/src/fp_256.rs @@ -767,7 +767,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[0], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1 + carry2; + r[3] = carry1.wrapping_add(carry2); // Iteration 1. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[1], &mut carry1); @@ -781,7 +781,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[1], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1 + carry2; + r[3] = carry1.wrapping_add(carry2); // Iteration 2. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[2], &mut carry1); @@ -795,7 +795,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[2], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1 + carry2; + r[3] = carry1.wrapping_add(carry2); // Iteration 3. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[3], &mut carry1); @@ -809,7 +809,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[3], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1 + carry2; + r[3] = carry1.wrapping_add(carry2); (self.0).0 = r; self.reduce(); diff --git a/fields/src/fp_384.rs b/fields/src/fp_384.rs index 1e60a18c2f..7f82ef6e53 100644 --- a/fields/src/fp_384.rs +++ b/fields/src/fp_384.rs @@ -790,7 +790,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[0], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1 + carry2; + r[5] = carry1.wrapping_add(carry2); // Iteration 1. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[1], &mut carry1); @@ -810,7 +810,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[1], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1 + carry2; + r[5] = carry1.wrapping_add(carry2); // Iteration 2. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[2], &mut carry1); @@ -830,7 +830,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[2], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1 + carry2; + r[5] = carry1.wrapping_add(carry2); // Iteration 3. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[3], &mut carry1); @@ -850,7 +850,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[3], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1 + carry2; + r[5] = carry1.wrapping_add(carry2); // Iteration 4. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[4], &mut carry1); @@ -870,7 +870,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[4], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1 + carry2; + r[5] = carry1.wrapping_add(carry2); // Iteration 5. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[5], &mut carry1); @@ -890,7 +890,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[5], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1 + carry2; + r[5] = carry1.wrapping_add(carry2); (self.0).0 = r; self.reduce(); From 88a0d800d6dcc30b0a08b14afe84e815d2932002 Mon Sep 17 00:00:00 2001 From: raychu86 <14917648+raychu86@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:34:37 -0700 Subject: [PATCH 2/5] Use a seeded rng for inputs and substack during deployment verification --- synthesizer/process/Cargo.toml | 3 +++ synthesizer/process/src/stack/deploy.rs | 12 +++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/synthesizer/process/Cargo.toml b/synthesizer/process/Cargo.toml index 294a43b9bd..f34193160a 100644 --- a/synthesizer/process/Cargo.toml +++ b/synthesizer/process/Cargo.toml @@ -113,6 +113,9 @@ version = "0.12" [dependencies.rand] version = "0.8" +[dependencies.rand_chacha] +version = "0.3" + [dependencies.rayon] version = "1" optional = true diff --git a/synthesizer/process/src/stack/deploy.rs b/synthesizer/process/src/stack/deploy.rs index 431cf2acb2..b9d92380b4 100644 --- a/synthesizer/process/src/stack/deploy.rs +++ b/synthesizer/process/src/stack/deploy.rs @@ -93,6 +93,12 @@ impl Stack { "The number of functions in the program does not match the number of verifying keys" ); + // Create a seeded rng to use for input value and sub-stack generation. + // This is needed to ensure that the verification results of deployments are consistent across all parties, + // because currently there is a possible flakiness due to overflows in Field to Scalar casting. + let seed = u64::from_bytes_le(&deployment.to_deployment_id()?.to_bytes_le()?[0..8])?; + let mut seeded_rng = rand_chacha::ChaChaRng::seed_from_u64(seed); + // Iterate through the program functions and construct the callstacks and corresponding assignments. for (function, (_, (verifying_key, _))) in deployment.program().functions().values().zip_eq(deployment.verifying_keys()) @@ -111,9 +117,9 @@ impl Stack { // Retrieve the external stack. let stack = self.get_external_stack(locator.program_id())?; // Sample the input. - stack.sample_value(&burner_address, &ValueType::Record(*locator.resource()), rng) + stack.sample_value(&burner_address, &ValueType::Record(*locator.resource()), &mut seeded_rng) } - _ => self.sample_value(&burner_address, input_type, rng), + _ => self.sample_value(&burner_address, input_type, &mut seeded_rng), }) .collect::>>()?; lap!(timer, "Sample the inputs"); @@ -154,7 +160,7 @@ impl Stack { } // Verify the certificates. - let rngs = (0..call_stacks.len()).map(|_| StdRng::from_seed(rng.gen())).collect::>(); + let rngs = (0..call_stacks.len()).map(|_| StdRng::from_seed(seeded_rng.gen())).collect::>(); cfg_into_iter!(call_stacks).zip_eq(deployment.verifying_keys()).zip_eq(rngs).try_for_each( |(((function_name, call_stack, assignments), (_, (verifying_key, certificate))), mut rng)| { // Synthesize the circuit. From 6296b95d2928f5ec58221760b8fd225d939fac0c Mon Sep 17 00:00:00 2001 From: raychu86 <14917648+raychu86@users.noreply.github.com> Date: Fri, 23 Aug 2024 14:36:51 -0700 Subject: [PATCH 3/5] Add tests for deployment verification consistency --- Cargo.lock | 3 ++ ledger/Cargo.toml | 6 +++ ledger/src/lib.rs | 2 + ledger/src/tests.rs | 115 +++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 125 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 01a7d51dba..3be34216e7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3091,6 +3091,7 @@ dependencies = [ "rand", "rayon", "serde_json", + "snarkvm-circuit", "snarkvm-console", "snarkvm-ledger-authority", "snarkvm-ledger-block", @@ -3101,6 +3102,7 @@ dependencies = [ "snarkvm-ledger-store", "snarkvm-ledger-test-helpers", "snarkvm-synthesizer", + "snarkvm-utilities", "time", "tracing", ] @@ -3444,6 +3446,7 @@ dependencies = [ "once_cell", "parking_lot", "rand", + "rand_chacha", "rayon", "serde_json", "snarkvm-circuit", diff --git a/ledger/Cargo.toml b/ledger/Cargo.toml index 709a32abe0..4147716ef4 100644 --- a/ledger/Cargo.toml +++ b/ledger/Cargo.toml @@ -156,3 +156,9 @@ path = "./test-helpers" [dev-dependencies.serde_json] version = "1.0" features = [ "preserve_order" ] + +[dev-dependencies.snarkvm-circuit] +path = "../circuit" + +[dev-dependencies.snarkvm-utilities] +path = "../utilities" diff --git a/ledger/src/lib.rs b/ledger/src/lib.rs index 957d45e783..7f81b9005b 100644 --- a/ledger/src/lib.rs +++ b/ledger/src/lib.rs @@ -391,9 +391,11 @@ pub(crate) mod test_helpers { }; use ledger_block::Block; use ledger_store::ConsensusStore; + use snarkvm_circuit::network::AleoV0; use synthesizer::vm::VM; pub(crate) type CurrentNetwork = MainnetV0; + pub(crate) type CurrentAleo = AleoV0; #[cfg(not(feature = "rocks"))] pub(crate) type CurrentLedger = diff --git a/ledger/src/tests.rs b/ledger/src/tests.rs index b16971f69a..5031646394 100644 --- a/ledger/src/tests.rs +++ b/ledger/src/tests.rs @@ -14,7 +14,7 @@ use crate::{ advance::split_candidate_solutions, - test_helpers::{CurrentLedger, CurrentNetwork}, + test_helpers::{CurrentAleo, CurrentLedger, CurrentNetwork}, Ledger, RecordsFilter, }; @@ -28,6 +28,7 @@ use console::{ use ledger_block::{ConfirmedTransaction, Execution, Ratify, Rejected, Transaction}; use ledger_committee::{Committee, MIN_VALIDATOR_STAKE}; use ledger_store::{helpers::memory::ConsensusMemory, ConsensusStore}; +use snarkvm_utilities::try_vm_runtime; use synthesizer::{program::Program, vm::VM, Stack}; use indexmap::IndexMap; @@ -2346,6 +2347,118 @@ finalize is_id: ledger.advance_to_next_block(&block_3).unwrap(); } +#[test] +fn test_deployment_with_cast_from_field_to_scalar() { + // Initialize an RNG. + let rng = &mut TestRng::default(); + + const ITERATIONS: usize = 10; + + // Construct a program that casts a field to a scalar. + let program = Program::::from_str( + r" +program test_cast_field_to_scalar.aleo; +function foo: + input r0 as field.public; + cast r0 into r1 as scalar;", + ) + .unwrap(); + + // Constructs a program that has a struct with a field that is cast to a scalar. + let program_2 = Program::::from_str( + r" +program test_cast_f_to_s_struct.aleo; + +struct message: + first as scalar; + +function foo: + input r0 as field.public; + cast r0 into r1 as scalar; + cast r1 into r2 as message;", + ) + .unwrap(); + + // Constructs a program that has an array of scalars cast from fields. + let program_3 = Program::::from_str( + r" +program test_cast_f_to_s_array.aleo; + +function foo: + input r0 as field.public; + cast r0 into r1 as scalar; + cast r1 r1 r1 r1 into r2 as [scalar; 4u32];", + ) + .unwrap(); + + // Initialize the test environment. + let crate::test_helpers::TestEnv { ledger, private_key, .. } = crate::test_helpers::sample_test_env(rng); + + // Deploy the programs. Keep attempting to create a deployment until it is successful. + let deployment_tx = { + let mut attempts = 0; + loop { + if attempts >= ITERATIONS { + panic!("Failed to craft deployment after {ITERATIONS} attempts"); + } + match try_vm_runtime!(|| ledger.vm().deploy(&private_key, &program, None, 0, None, rng)) { + Ok(result) => break result.unwrap(), + Err(_) => attempts += 1, + } + } + }; + let deployment_tx_2 = { + let mut attempts = 0; + loop { + if attempts >= ITERATIONS { + panic!("Failed to craft deployment after {ITERATIONS} attempts"); + } + match try_vm_runtime!(|| ledger.vm().deploy(&private_key, &program_2, None, 0, None, rng)) { + Ok(result) => break result.unwrap(), + Err(_) => attempts += 1, + } + } + }; + let deployment_tx_3 = { + let mut attempts = 0; + loop { + if attempts >= ITERATIONS { + panic!("Failed to craft deployment after {ITERATIONS} attempts"); + } + match try_vm_runtime!(|| ledger.vm().deploy(&private_key, &program_3, None, 0, None, rng)) { + Ok(result) => break result.unwrap(), + Err(_) => attempts += 1, + } + } + }; + + // Verify the deployment under different RNGs to ensure the deployment is valid. + for _ in 0..ITERATIONS { + let process = ledger.vm().process().clone(); + // Check that the verification of the deployments are consistent. + let expected_result = ledger.vm().check_transaction(&deployment_tx, None, rng).is_ok(); + let deployment = deployment_tx.deployment().unwrap().clone(); + for _ in 0..ITERATIONS { + let result = process.read().verify_deployment::(&deployment, rng).is_ok(); + assert_eq!(result, expected_result); + } + + let expected_result = ledger.vm().check_transaction(&deployment_tx_2, None, rng).is_ok(); + let deployment_2 = deployment_tx_2.deployment().unwrap().clone(); + for _ in 0..ITERATIONS { + let result = process.read().verify_deployment::(&deployment_2, rng).is_ok(); + assert_eq!(result, expected_result); + } + + let expected_result = ledger.vm().check_transaction(&deployment_tx_3, None, rng).is_ok(); + let deployment_3 = deployment_tx_3.deployment().unwrap().clone(); + for _ in 0..ITERATIONS { + let result = process.read().verify_deployment::(&deployment_3, rng).is_ok(); + assert_eq!(result, expected_result); + } + } +} + // These tests require the proof targets to be low enough to be able to generate **valid** solutions. // This requires the 'test' feature to be enabled for the `console` dependency. #[cfg(feature = "test")] From 1c6c84d9a5f826bfe6e65884530d38d63da1b9fe Mon Sep 17 00:00:00 2001 From: raychu86 <14917648+raychu86@users.noreply.github.com> Date: Mon, 26 Aug 2024 09:56:30 -0700 Subject: [PATCH 4/5] Revert "refactor: use explicit wrapping addition in Fp*::mul_assign" This reverts commit 2482c9b2cc8a77c0985430aa2c1178aaa67e2d63. --- fields/src/fp_256.rs | 8 ++++---- fields/src/fp_384.rs | 12 ++++++------ 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/fields/src/fp_256.rs b/fields/src/fp_256.rs index bb70c0cc4f..80f69a635b 100644 --- a/fields/src/fp_256.rs +++ b/fields/src/fp_256.rs @@ -767,7 +767,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[0], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1.wrapping_add(carry2); + r[3] = carry1 + carry2; // Iteration 1. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[1], &mut carry1); @@ -781,7 +781,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[1], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1.wrapping_add(carry2); + r[3] = carry1 + carry2; // Iteration 2. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[2], &mut carry1); @@ -795,7 +795,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[2], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1.wrapping_add(carry2); + r[3] = carry1 + carry2; // Iteration 3. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[3], &mut carry1); @@ -809,7 +809,7 @@ impl<'a, P: Fp256Parameters> MulAssign<&'a Self> for Fp256

{ r[3] = fa::mac_with_carry(r[3], (self.0).0[3], (other.0).0[3], &mut carry1); r[2] = fa::mac_with_carry(r[3], k, P::MODULUS.0[3], &mut carry2); - r[3] = carry1.wrapping_add(carry2); + r[3] = carry1 + carry2; (self.0).0 = r; self.reduce(); diff --git a/fields/src/fp_384.rs b/fields/src/fp_384.rs index 7f82ef6e53..1e60a18c2f 100644 --- a/fields/src/fp_384.rs +++ b/fields/src/fp_384.rs @@ -790,7 +790,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[0], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1.wrapping_add(carry2); + r[5] = carry1 + carry2; // Iteration 1. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[1], &mut carry1); @@ -810,7 +810,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[1], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1.wrapping_add(carry2); + r[5] = carry1 + carry2; // Iteration 2. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[2], &mut carry1); @@ -830,7 +830,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[2], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1.wrapping_add(carry2); + r[5] = carry1 + carry2; // Iteration 3. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[3], &mut carry1); @@ -850,7 +850,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[3], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1.wrapping_add(carry2); + r[5] = carry1 + carry2; // Iteration 4. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[4], &mut carry1); @@ -870,7 +870,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[4], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1.wrapping_add(carry2); + r[5] = carry1 + carry2; // Iteration 5. r[0] = fa::mac(r[0], (self.0).0[0], (other.0).0[5], &mut carry1); @@ -890,7 +890,7 @@ impl<'a, P: Fp384Parameters> MulAssign<&'a Self> for Fp384

{ r[5] = fa::mac_with_carry(r[5], (self.0).0[5], (other.0).0[5], &mut carry1); r[4] = fa::mac_with_carry(r[5], k, P::MODULUS.0[5], &mut carry2); - r[5] = carry1.wrapping_add(carry2); + r[5] = carry1 + carry2; (self.0).0 = r; self.reduce(); From 7e8005cb0af875dbc918f1f966ff49c39b1de996 Mon Sep 17 00:00:00 2001 From: raychu86 <14917648+raychu86@users.noreply.github.com> Date: Mon, 26 Aug 2024 10:03:43 -0700 Subject: [PATCH 5/5] Simplify test --- ledger/src/tests.rs | 75 +++++++++++++++++---------------------------- 1 file changed, 28 insertions(+), 47 deletions(-) diff --git a/ledger/src/tests.rs b/ledger/src/tests.rs index 5031646394..54086f2d0e 100644 --- a/ledger/src/tests.rs +++ b/ledger/src/tests.rs @@ -2394,68 +2394,49 @@ function foo: // Initialize the test environment. let crate::test_helpers::TestEnv { ledger, private_key, .. } = crate::test_helpers::sample_test_env(rng); - // Deploy the programs. Keep attempting to create a deployment until it is successful. - let deployment_tx = { + // Create a helper method to deploy the programs. + let deploy_program = |program: &Program, rng: &mut TestRng| { let mut attempts = 0; loop { if attempts >= ITERATIONS { panic!("Failed to craft deployment after {ITERATIONS} attempts"); } - match try_vm_runtime!(|| ledger.vm().deploy(&private_key, &program, None, 0, None, rng)) { - Ok(result) => break result.unwrap(), - Err(_) => attempts += 1, - } - } - }; - let deployment_tx_2 = { - let mut attempts = 0; - loop { - if attempts >= ITERATIONS { - panic!("Failed to craft deployment after {ITERATIONS} attempts"); - } - match try_vm_runtime!(|| ledger.vm().deploy(&private_key, &program_2, None, 0, None, rng)) { - Ok(result) => break result.unwrap(), - Err(_) => attempts += 1, - } - } - }; - let deployment_tx_3 = { - let mut attempts = 0; - loop { - if attempts >= ITERATIONS { - panic!("Failed to craft deployment after {ITERATIONS} attempts"); - } - match try_vm_runtime!(|| ledger.vm().deploy(&private_key, &program_3, None, 0, None, rng)) { + match try_vm_runtime!(|| ledger.vm().deploy(&private_key, program, None, 0, None, rng)) { Ok(result) => break result.unwrap(), Err(_) => attempts += 1, } } }; + // Deploy the programs. Keep attempting to create a deployment until it is successful. + let deployment_tx = deploy_program(&program, rng); + let deployment_tx_2 = deploy_program(&program_2, rng); + let deployment_tx_3 = deploy_program(&program_3, rng); + // Verify the deployment under different RNGs to ensure the deployment is valid. for _ in 0..ITERATIONS { let process = ledger.vm().process().clone(); - // Check that the verification of the deployments are consistent. - let expected_result = ledger.vm().check_transaction(&deployment_tx, None, rng).is_ok(); - let deployment = deployment_tx.deployment().unwrap().clone(); - for _ in 0..ITERATIONS { - let result = process.read().verify_deployment::(&deployment, rng).is_ok(); - assert_eq!(result, expected_result); - } - - let expected_result = ledger.vm().check_transaction(&deployment_tx_2, None, rng).is_ok(); - let deployment_2 = deployment_tx_2.deployment().unwrap().clone(); - for _ in 0..ITERATIONS { - let result = process.read().verify_deployment::(&deployment_2, rng).is_ok(); - assert_eq!(result, expected_result); - } + // Create a helper method to verify the deployments. + let verify_deployment = |deployment_tx: &Transaction, rng: &mut TestRng| { + let expected_result = match try_vm_runtime!(|| ledger.vm().check_transaction(deployment_tx, None, rng)) { + Ok(result) => result.is_ok(), + Err(_) => false, + }; + let deployment = deployment_tx.deployment().unwrap().clone(); + for _ in 0..ITERATIONS { + let result = + match try_vm_runtime!(|| process.read().verify_deployment::(&deployment, rng)) { + Ok(result) => result.is_ok(), + Err(_) => false, + }; + assert_eq!(result, expected_result); + } + }; - let expected_result = ledger.vm().check_transaction(&deployment_tx_3, None, rng).is_ok(); - let deployment_3 = deployment_tx_3.deployment().unwrap().clone(); - for _ in 0..ITERATIONS { - let result = process.read().verify_deployment::(&deployment_3, rng).is_ok(); - assert_eq!(result, expected_result); - } + // Verify the deployments. + verify_deployment(&deployment_tx, rng); + verify_deployment(&deployment_tx_2, rng); + verify_deployment(&deployment_tx_3, rng); } }