diff --git a/parameters/src/mainnet/resources/block.genesis b/parameters/src/mainnet/resources/block.genesis index 9eb4226636..36a3ab2e4d 100644 Binary files a/parameters/src/mainnet/resources/block.genesis and b/parameters/src/mainnet/resources/block.genesis differ diff --git a/parameters/src/mainnet/resources/fee_public.metadata b/parameters/src/mainnet/resources/fee_public.metadata index b94bca4f26..a4d5aa14c0 100644 --- a/parameters/src/mainnet/resources/fee_public.metadata +++ b/parameters/src/mainnet/resources/fee_public.metadata @@ -1,6 +1,6 @@ { - "prover_checksum": "88f6575a2f0e08d9768fa038081d3ccdb9d27f85cc52209007d35ea3ef51c1c4", + "prover_checksum": "d967fc683af43a0a01817283af05181f9f8277c49351ca664a642b0eb9ec9363", "prover_size": 29174402, - "verifier_checksum": "50ddf9c83807fc854d56afcda7171321d8fdef46271b3a3ea7b3c1485c3b193f", + "verifier_checksum": "1e8cc6ab1de9ec21d1559434c516698af40895df3e3d6afb0615495d0201955b", "verifier_size": 665 } \ No newline at end of file diff --git a/parameters/src/mainnet/resources/fee_public.verifier b/parameters/src/mainnet/resources/fee_public.verifier index d5a9df4ffa..1ae17cb8d2 100644 Binary files a/parameters/src/mainnet/resources/fee_public.verifier and b/parameters/src/mainnet/resources/fee_public.verifier differ diff --git a/synthesizer/program/src/resources/credits.aleo b/synthesizer/program/src/resources/credits.aleo index 51fc62e167..b557767eee 100644 --- a/synthesizer/program/src/resources/credits.aleo +++ b/synthesizer/program/src/resources/credits.aleo @@ -935,7 +935,7 @@ function fee_public: // Add the fee and priority fee amounts. add r0 r1 into r3; // Decrement the balance of the sender publicly. - async fee_public self.caller r3 into r4; + async fee_public self.signer r3 into r4; // Output the finalize future. output r4 as credits.aleo/fee_public.future; diff --git a/synthesizer/src/vm/mod.rs b/synthesizer/src/vm/mod.rs index 299f2057dc..0dc87ee8e4 100644 --- a/synthesizer/src/vm/mod.rs +++ b/synthesizer/src/vm/mod.rs @@ -1201,6 +1201,89 @@ function transfer: assert!(vm.contains_program(&ProgramID::from_str("test_program.aleo").unwrap())); } + #[test] + fn test_internal_fee_calls_are_invalid() { + let rng = &mut TestRng::default(); + + // Initialize a private key. + let private_key = sample_genesis_private_key(rng); + let view_key = ViewKey::try_from(&private_key).unwrap(); + + // Initialize the genesis block. + let genesis = sample_genesis_block(rng); + + // Initialize the VM. + let vm = sample_vm(); + // Update the VM. + vm.add_next_block(&genesis).unwrap(); + + // Fetch the unspent records. + let records = + genesis.transitions().cloned().flat_map(Transition::into_records).take(3).collect::>(); + trace!("Unspent Records:\n{:#?}", records); + let record_0 = records.values().next().unwrap().decrypt(&view_key).unwrap(); + + // Deploy the program. + let program = Program::from_str( + r" +import credits.aleo; +program test_program.aleo; + +function call_fee_public: + input r0 as u64.private; + input r1 as u64.private; + input r2 as field.private; + call credits.aleo/fee_public r0 r1 r2 into r3; + async call_fee_public r3 into r4; + output r4 as test_program.aleo/call_fee_public.future; + +finalize call_fee_public: + input r0 as credits.aleo/fee_public.future; + await r0; + +function call_fee_private: + input r0 as credits.aleo/credits.record; + input r1 as u64.private; + input r2 as u64.private; + input r3 as field.private; + call credits.aleo/fee_private r0 r1 r2 r3 into r4; + output r4 as credits.aleo/credits.record; +", + ) + .unwrap(); + + let deployment = vm.deploy(&private_key, &program, None, 0, None, rng).unwrap(); + assert!(vm.check_transaction(&deployment, None, rng).is_ok()); + vm.add_next_block(&sample_next_block(&vm, &private_key, &[deployment], rng).unwrap()).unwrap(); + + // Execute the programs. + let internal_base_fee_amount: u64 = rng.gen_range(1..1000); + let internal_priority_fee_amount: u64 = rng.gen_range(1..1000); + + // Ensure that the transaction that calls `fee_public` internally cannot be generated. + let inputs = [ + Value::::from_str(&format!("{}u64", internal_base_fee_amount)).unwrap(), + Value::::from_str(&format!("{}u64", internal_priority_fee_amount)).unwrap(), + Value::::from_str("1field").unwrap(), + ]; + assert!( + vm.execute(&private_key, ("test_program.aleo", "call_fee_public"), inputs.into_iter(), None, 0, None, rng) + .is_err() + ); + + // Ensure that the transaction that calls `fee_private` internally cannot be generated. + let inputs = [ + Value::::Record(record_0), + Value::::from_str(&format!("{}u64", internal_base_fee_amount)).unwrap(), + Value::::from_str(&format!("{}u64", internal_priority_fee_amount)).unwrap(), + Value::::from_str("1field").unwrap(), + ]; + assert!( + vm.execute(&private_key, ("test_program.aleo", "call_fee_private"), inputs.into_iter(), None, 0, None, rng) + .is_err() + ); + } + #[test] fn test_deployment_synthesis_overload() { let rng = &mut TestRng::default();