Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Constrained functions can be unconstrained at the same time #11725

Closed
NikolayKostadinov21 opened this issue Feb 4, 2025 · 3 comments · Fixed by #11815
Closed

Constrained functions can be unconstrained at the same time #11725

NikolayKostadinov21 opened this issue Feb 4, 2025 · 3 comments · Fixed by #11815
Assignees
Labels
C-aztec.nr Component: Aztec smart contract framework

Comments

@NikolayKostadinov21
Copy link

Summary

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 }
@Maddiaa0
Copy link
Member

Maddiaa0 commented Feb 7, 2025

Ah interesting! Thank you for filing

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!

@Maddiaa0
Copy link
Member

Maddiaa0 commented Feb 7, 2025

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:

Image

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!

@Maddiaa0 Maddiaa0 self-assigned this Feb 7, 2025
@Maddiaa0
Copy link
Member

Maddiaa0 commented Feb 7, 2025

This should be available in the next release ! Feel free to reopen if you think we need to alter the solution

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
C-aztec.nr Component: Aztec smart contract framework
Projects
None yet
2 participants