You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
You are able to place unconstrained on a constrained function. Furthermore, you are able to invoke this "constrained unconstrained function" in this case double in another constrained function.
Aztec version - 0.73.0
compiler version - 0.35.0
Example
use dep::aztec::macros::aztec;
mod test;
#[aztec]
contract Main {
use dep::aztec::{macros::{functions::{initializer, public, view, private}}};
#[public]
#[initializer]
fn constructor() {}
#[public]
#[view]
unconstrained fn double(x: Field) -> Field { x * 2 }
#[private]
unconstrained fn add_by_itself(x: Field) -> Field { x + x }
#[public]
#[view]
fn nested_double(x: Field) -> Field { double(x) }
unconstrained fn triple(x: Field) -> pub Field { x * 3 }
fn quadriple(x: Field) -> pub Field { x * 4 }
}
Testing
Tests are passing successfully
use dep::aztec::{
prelude::AztecAddress,
protocol_types::{
contract_instance::ContractInstance,
storage::map::derive_storage_slot_in_map,
},
test::helpers::test_environment::TestEnvironment,
};
use dep::aztec::oracle::{execution::get_block_number, storage::storage_read};
use crate::Main;
unconstrained pub fn setup() -> (&mut TestEnvironment, AztecAddress) {
let mut env = TestEnvironment::new();
let initializer_call_interface = Main::interface().constructor();
let main_contract = env.deploy_self("Main").with_public_void_initializer(
initializer_call_interface,
);
(&mut env, main_contract.to_address())
}
#[test]
unconstrained fn test_set_feeds() {
let (env, main_contract_address) = setup();
let key = 3;
let get_just_field = Main::at(main_contract_address).nested_double(key).view(&mut env.public());
println("get_just_field");
println(get_just_field as u32);
}
Expected behaviour
The compiler should have said something like: the function double must have a verification key.
Notes
private functions can also be unconstrained.
e.g.
#[private]
unconstrained fn add_by_itself(x: Field) -> Field { x + x }
The code compiles, however the only difference is that when the above tests are invoked, the following error is prompted:
aztec-nargo-1 | Failed calling external resolver. ErrorObject { code: InvalidRequest, message: "Private function add_by_itself must have a verification key", data: None }
The text was updated successfully, but these errors were encountered:
In the public case, this is somewhat expected behaviour, functions marked as public end up being compiled as bytecode which is the same output of an unconstrained function, although you are correct this is a footgun!
This fails at runtime in the private case as #[private] should not produce public bytecode, but instead it will produce this verification key.
We can add a check that anything annotated with the #[private] or #[public] macro will not accept being further modified with unconstrained to prevent this footgun!
In #11815 I have added checks into the macro to prevent the above occuring, when compiling the example above it now gives this as error output:
The stack traces are showing where the panic occurs in the #[private] and #[public] macro. But the error message includes the function name, so I hope this is a good enough solution!
Summary
You are able to place
unconstrained
on a constrained function. Furthermore, you are able to invoke this "constrained unconstrained function" in this casedouble
in another constrained function.Aztec version -
0.73.0
compiler version -
0.35.0
Example
Testing
Tests are passing successfully
Expected behaviour
The compiler should have said something like:
the function
doublemust have a verification key.
Notes
private
functions can also beunconstrained
.e.g.
The code compiles, however the only difference is that when the above tests are invoked, the following error is prompted:
The text was updated successfully, but these errors were encountered: