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

[Tracking Issue]: Macro discussions, library transforming and long term goals #2419

Closed
Maddiaa0 opened this issue Aug 23, 2023 · 4 comments
Closed

Comments

@Maddiaa0
Copy link
Member

Maddiaa0 commented Aug 23, 2023

Problem

In recent discussions it was raised that noir will aim to support complex features that are required for smart contract languages. e,g, ways to support additions of syntactic sugar.

Why do we want this

It may be the case that teams (like aztec) would like to build meta-frameworks on top of noir. Much like in solana we have anchor lang which exists as a meta framework on top of rust.

Anchor abstracts the guts of the solana api and creates a nice developer framework that protects developers from common footguns and makes the devex alot nicer.

A quick example for this syntax is shown below:
For example what originally was:

    fn mint(
        inputs: PrivateContextInputs,
        amount: Field, 
        owner: Field
    ) -> distinct pub abi::PrivateCircuitPublicInputs {
        let storage = Storage::init();
        let mut context = PrivateContext::new(inputs, abi::hash_args([amount, owner]));

        // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call.
        let owner_balance = storage.balances.at(owner);
        send_note(&mut context, owner_balance, amount, owner);
        emit_unencrypted_log(&mut context, "Coins minted");

        // Return private circuit public inputs. All private functions need to return this as it is part of the input of the private kernel..
        context.finish()
    }

can instead be written as:

   #[aztec(private)]
    fn mint(
        amount: Field, 
        owner: Field
    )  {
        let storage = Storage::init();

        // Insert new note to a set of user notes and emit the newly created encrypted note preimage via oracle call.
        let owner_balance = storage.balances.at(owner);
        send_note(&mut context, owner_balance, amount, owner);
        emit_unencrypted_log(&mut context, "Coins minted");
    }

Custom annotations could be used (like macros) to transform the ast of functions and remove ugly and distracting boilerplate.

Short Term Goals (Hard deadline: completion by 15th September 2023)

Related Issues to the short term goals of this issue

Stretch goals support

Long term goals

The long term goals associated with this issue have an arbitrary time horizon and should not be direct blockers for stakeholders. They are rather aligned with supporting noir's long term vision.

The following work is not captured outside of this issue as no formal spec has been decided on, it is included to spark discussions about solutions that can remove stakeholder specific feature flags living in the code base

Abilities syntax

This syntax comes out of a conversation between kev and jake over how to remove the trans-formative attributes introduced in #2403.

The overarching idea of the abilities syntax is that we can polyfill arguments and variables into a method. The best mental model I have come across when thinking about it is that it is a combination between creating a facade class to inject arguments and a solidity modifier to extend a functions ability.

In the examples below, the with aztec3 will make a context available, and include the aztec kernel circuit inputs as the first parameter. Similar to how the hacky macro syntax above works, but at a language level.

Although nice solution, it will likely not exist in the short term due to its dependence on traits.

// (we should allow ‘using Aztec3’ on a contract to apply to each contract fn automatically?)
fn foo(x : PrivateField) with Aztec3 {
    x += 2; // impl Add for PrivateField
}

impl Add for PrivateField {
    fn add(self, other: Self) -> Self with Context {
        let context = Aztec3::get_mut_context();
        context.add(self, other);
    }
}

ability Aztec3 : Context {
    drop() { ... }
    contract _function_signauture(Context) -> [Field;12];
}

ability Context {
    get_mut_context() -> &mut Context {}
}

fn foo(mut context : PrivateContext, x : Field) -> [Field; 12] {
       context.add_something();

       context.finalize()
}
@Maddiaa0 Maddiaa0 added enhancement New feature or request discussion and removed enhancement New feature or request labels Aug 23, 2023
@Savio-Sou
Copy link
Collaborator

Savio-Sou commented Aug 30, 2023

Thanks for creating the issue!

@kevaundray should we replace / merge issues in #1378 into this?

@jfecher
Copy link
Contributor

jfecher commented Aug 8, 2024

Update: much of this has been implemented in Noir's new metaprogramming features here: #4594. Although implementing the full transformation for the mint example here likely requires several more comptime API functions which are still unimplemented. The remaining metaprogramming work is largely just adding more of these helper functions

@Thunkar
Copy link
Contributor

Thunkar commented Sep 26, 2024

After AztecProtocol/aztec-packages#8438, I think @Maddiaa0 you can do the honors and close this 😄

@Maddiaa0
Copy link
Member Author

image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Status: Done
Development

No branches or pull requests

4 participants