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

feat: Check initializer by default in private functions #4832

Merged
merged 10 commits into from
Mar 1, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ contract AppSubscription {

// Constructs the contract
#[aztec(private)]
#[aztec(initializer)]
fn constructor(
target_address: AztecAddress,
subscription_recipient_address: AztecAddress,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ contract Counter {

// docs:start:constructor
#[aztec(private)]
#[aztec(initializer)]
fn constructor(headstart: u64, owner: AztecAddress) {
let counters = storage.counters;
counters.at(owner).add(headstart, owner);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ contract EasyPrivateToken {
* initialize the contract's initial state variables.
*/
#[aztec(private)]
#[aztec(initializer)]
fn constructor(initial_supply: u64, owner: AztecAddress) {
let balances = storage.balances;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@ contract EasyPrivateVoting {
// docs:end:storage_struct

// docs:start:constructor
#[aztec(private)] // annotation to mark function as private and expose private context
#[aztec(private)]
#[aztec(initializer)] // annotation to mark function as private and expose private context
fn constructor(admin: AztecAddress) { // called when contract is deployed
context.call_public_function(
// we cannot update public state directly from private function but we can call public function (which queues it)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ contract EcdsaAccount {

// Creates a new account out of an ECDSA public key to use for signature verification
#[aztec(private)]
#[aztec(initializer)]
fn constructor(signing_pub_key_x: pub [u8; 32], signing_pub_key_y: pub [u8; 32]) {
let this = context.this_address();
let mut pub_key_note = EcdsaPublicKeyNote::new(signing_pub_key_x, signing_pub_key_y, this);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ contract Escrow {
// Creates a new instance
// docs:start:constructor
#[aztec(private)]
#[aztec(initializer)]
fn constructor(owner: pub AztecAddress) {
let this = context.this_address();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ contract FPC {
}

#[aztec(private)]
#[aztec(initializer)]
fn constructor(other_asset: AztecAddress, fee_asset: AztecAddress) {
let selector = FunctionSelector::from_signature("_initialize((Field),(Field))");
context.call_public_function(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ contract ImportTest {
ManyNotesADeepStructTestCodeGenStruct
};

// TODO(@spalladino): Delete all empty constructors
#[aztec(private)]
fn constructor(
) {}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ contract InclusionProofs {
}

#[aztec(private)]
#[aztec(initializer)]
fn constructor(public_value: Field) {
let selector = FunctionSelector::from_signature("_initialize(Field)");
context.call_public_function(context.this_address(), selector, [public_value]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,7 @@ contract Lending {

// Constructs the contract.
#[aztec(private)]
#[aztec(initializer)]
fn constructor(
) {}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ contract SchnorrAccount {

// Constructs the contract
#[aztec(private)]
#[aztec(initializer)]
fn constructor(signing_pub_key_x: pub Field, signing_pub_key_y: pub Field) {
let this = context.this_address();
// docs:start:initialize
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,6 @@ contract StatefulTest {
}

#[aztec(private)]
#[aztec(initcheck)]
fn create_note(owner: AztecAddress, value: Field) {
if (value != 0) {
let loc = storage.notes.at(owner);
Expand All @@ -34,6 +33,7 @@ contract StatefulTest {
}

#[aztec(private)]
#[aztec(noinitcheck)]
fn create_note_no_init_check(owner: AztecAddress, value: Field) {
if (value != 0) {
let loc = storage.notes.at(owner);
Expand All @@ -54,6 +54,7 @@ contract StatefulTest {
}

#[aztec(private)]
#[aztec(noinitcheck)]
fn destroy_and_create_no_init_check(recipient: AztecAddress, amount: Field) {
let sender = context.msg_sender();

Expand Down
18 changes: 16 additions & 2 deletions noir-projects/noir-contracts/contracts/test_contract/src/main.nr
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ contract Test {
// docs:end:unencrypted_import

use dep::aztec::{
context::{Context, inputs::private_context_inputs::PrivateContextInputs}, hash::pedersen_hash,
context::{Context, inputs::private_context_inputs::PrivateContextInputs},
hash::{pedersen_hash, compute_secret_hash},
context::PrivateContext,
note::{
note_header::NoteHeader, utils as note_utils, lifecycle::{create_note, destroy_note},
Expand All @@ -20,7 +21,7 @@ contract Test {
},
deploy::{deploy_contract as aztec_deploy_contract},
oracle::{get_public_key::get_public_key as get_public_key_oracle, context::get_portal_address, rand::rand},
state_vars::PrivateImmutable, log::emit_unencrypted_log_from_private
state_vars::{PrivateImmutable, PrivateSet}, log::emit_unencrypted_log_from_private
};
use dep::token_portal_content_hash_lib::{get_mint_private_content_hash, get_mint_public_content_hash};
use dep::field_note::field_note::FieldNote;
Expand All @@ -33,8 +34,10 @@ contract Test {

struct Storage {
example_constant: PrivateImmutable<FieldNote>,
example_set: PrivateSet<FieldNote>,
}

// TODO(@spalladino): Delete all empty constructors
#[aztec(private)]
// docs:start:empty-constructor
fn constructor() {}
Expand Down Expand Up @@ -350,6 +353,17 @@ contract Test {
aztec_deploy_contract(&mut context, target);
}

#[aztec(private)]
// Adapted from TokenContract#redeem_shield but without an initcheck so it can be run in simulator/src/client/private_execution.test.ts
fn consume_note_from_secret(secret: Field) {
let notes_set = storage.example_set;
let secret_hash = compute_secret_hash(secret);
let options = NoteGetterOptions::new().select(0, secret_hash, Option::none()).set_limit(1);
let notes = notes_set.get_notes(options);
let note = notes[0].unwrap_unchecked();
notes_set.remove(note);
}

unconstrained fn get_constant() -> pub Field {
let constant = storage.example_constant.view_note();
constant.value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ contract TokenBlacklist {

// docs:start:constructor
#[aztec(private)]
#[aztec(initializer)]
fn constructor(admin: AztecAddress, slow_updates_contract: AztecAddress) {
// docs:end:constructor
let selector = FunctionSelector::from_signature("_initialize((Field),(Field))");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ contract TokenBridge {

// Constructs the contract.
#[aztec(private)]
#[aztec(initializer)]
fn constructor(token: AztecAddress) {
let selector = FunctionSelector::from_signature("_initialize((Field))");
context.call_public_function(context.this_address(), selector, [token.to_field()]);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@ contract Token {

// docs:start:constructor
#[aztec(private)]
#[aztec(initializer)]
fn constructor(admin: AztecAddress, name: str<31>, symbol: str<31>, decimals: u8) {
let selector = FunctionSelector::from_signature("_initialize((Field),(Field),(Field),u8)");
let name_s = FieldCompressedString::from_string(name);
Expand Down
22 changes: 16 additions & 6 deletions noir/noir-repo/aztec_macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -435,22 +435,32 @@ fn transform_module(
}
}

let has_initializer = module.functions.iter().any(|func| {
func.def
.attributes
.secondary
.iter()
.any(|attr| is_custom_attribute(&attr, "aztec(initializer)"))
});

for func in module.functions.iter_mut() {
let mut is_private = false;
let mut is_public = false;
let mut is_public_vm = false;
let mut is_initializer = false;
let mut skip_init_check = true; // Default to true once we're confident that the approach works
let mut insert_init_check = has_initializer;

for secondary_attribute in func.def.attributes.secondary.clone() {
if is_custom_attribute(&secondary_attribute, "aztec(private)") {
is_private = true;
} else if is_custom_attribute(&secondary_attribute, "aztec(initializer)") {
is_initializer = true;
} else if is_custom_attribute(&secondary_attribute, "aztec(initcheck)") {
skip_init_check = false;
insert_init_check = false;
} else if is_custom_attribute(&secondary_attribute, "aztec(noinitcheck)") {
insert_init_check = false;
} else if is_custom_attribute(&secondary_attribute, "aztec(public)") {
is_public = true;
insert_init_check = false;
} else if is_custom_attribute(&secondary_attribute, "aztec(public-vm)") {
is_public_vm = true;
}
Expand All @@ -463,7 +473,7 @@ fn transform_module(
func,
storage_defined,
is_initializer,
skip_init_check,
insert_init_check,
)
.map_err(|err| (err, crate_graph.root_file_id))?;
has_transformed_module = true;
Expand Down Expand Up @@ -655,14 +665,14 @@ fn transform_function(
func: &mut NoirFunction,
storage_defined: bool,
is_initializer: bool,
skip_init_check: bool,
insert_init_check: bool,
) -> Result<(), AztecMacroError> {
let context_name = format!("{}Context", ty);
let inputs_name = format!("{}ContextInputs", ty);
let return_type_name = format!("{}CircuitPublicInputs", ty);

// Add initialization check
if !skip_init_check {
if insert_init_check {
if ty == "Public" {
let error = AztecMacroError::UnsupportedAttributes {
span: func.def.name.span(),
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/archiver/src/rpc/archiver_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
L1ToL2Message,
L2Block,
L2BlockL2Logs,
NullifierMembershipWitness,
TxReceipt,
} from '@aztec/circuit-types';
import { EthAddress, Fr } from '@aztec/circuits.js';
Expand All @@ -27,7 +28,7 @@ export const createArchiverClient = (url: string, fetch = makeFetch([1, 2, 3], t
L2Block,
L2BlockL2Logs,
},
{ TxReceipt },
{ TxReceipt, NullifierMembershipWitness },
false,
'archiver',
fetch,
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/archiver/src/rpc/archiver_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import {
L1ToL2Message,
L2Block,
L2BlockL2Logs,
NullifierMembershipWitness,
TxEffect,
TxReceipt,
} from '@aztec/circuit-types';
Expand Down Expand Up @@ -34,7 +35,7 @@ export function createArchiverRpcServer(archiverService: Archiver): JsonRpcServe
L2BlockL2Logs,
TxEffect,
},
{ TxReceipt },
{ TxReceipt, NullifierMembershipWitness },
['start', 'stop'],
);
}
3 changes: 2 additions & 1 deletion yarn-project/aztec-node/src/aztec-node/http_rpc_server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import {
L2Block,
L2BlockL2Logs,
LogId,
NullifierMembershipWitness,
SiblingPath,
Tx,
TxEffect,
Expand Down Expand Up @@ -43,7 +44,7 @@ export function createAztecNodeRpcServer(node: AztecNode) {
SiblingPath,
L1ToL2MessageAndIndex,
},
{ Tx, TxReceipt, L2BlockL2Logs },
{ Tx, TxReceipt, L2BlockL2Logs, NullifierMembershipWitness },
// disable methods not part of the AztecNode interface
['start', 'stop'],
);
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/aztec.js/src/rpc_clients/pxe_client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import {
L2BlockL2Logs,
LogId,
Note,
NullifierMembershipWitness,
PXE,
Tx,
TxEffect,
Expand Down Expand Up @@ -55,7 +56,7 @@ export const createPXEClient = (url: string, fetch = makeFetch([1, 2, 3], false)
TxExecutionRequest,
TxHash,
},
{ Tx, TxReceipt, L2BlockL2Logs },
{ Tx, TxReceipt, L2BlockL2Logs, NullifierMembershipWitness },
false,
'pxe',
fetch,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import { createJsonRpcClient, defaultFetch } from '@aztec/foundation/json-rpc/cl

import { ContractData, ExtendedContractData } from '../../contract_data.js';
import { AztecNode } from '../../interfaces/aztec-node.js';
import { NullifierMembershipWitness } from '../../interfaces/nullifier_tree.js';
import { L1ToL2MessageAndIndex } from '../../l1_to_l2_message.js';
import { L2Block } from '../../l2_block.js';
import { ExtendedUnencryptedL2Log, L2BlockL2Logs, LogId } from '../../logs/index.js';
Expand Down Expand Up @@ -40,7 +41,7 @@ export function createAztecNodeClient(url: string, fetch = defaultFetch): AztecN
SiblingPath,
L1ToL2MessageAndIndex,
},
{ Tx, TxReceipt, L2BlockL2Logs },
{ Tx, TxReceipt, L2BlockL2Logs, NullifierMembershipWitness },
false,
'node',
fetch,
Expand Down
16 changes: 16 additions & 0 deletions yarn-project/circuit-types/src/interfaces/nullifier_tree.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,20 @@ export class NullifierMembershipWitness {
public toFields(): Fr[] {
return [new Fr(this.index), ...this.leafPreimage.toFields(), ...this.siblingPath.toFields()];
}

public toJSON() {
return {
index: '0x' + this.index.toString(16),
leafPreimage: this.leafPreimage.toJSON(),
siblingPath: this.siblingPath.toString(),
};
}

static fromJSON(json: any): NullifierMembershipWitness {
return new NullifierMembershipWitness(
BigInt(json.index),
NullifierLeafPreimage.fromJSON(json.leafPreimage),
SiblingPath.fromString<typeof NULLIFIER_TREE_HEIGHT>(json.siblingPath),
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,14 @@ export class NullifierLeafPreimage implements IndexedTreeLeafPreimage {
return new NullifierLeafPreimage(this.nullifier, this.nextNullifier, this.nextIndex);
}

toJSON() {
return {
nullifier: this.nullifier.toString(),
nextNullifier: this.nextNullifier.toString(),
nextIndex: '0x' + this.nextIndex.toString(16),
};
}

static empty(): NullifierLeafPreimage {
return new NullifierLeafPreimage(Fr.ZERO, Fr.ZERO, 0n);
}
Expand All @@ -75,6 +83,14 @@ export class NullifierLeafPreimage implements IndexedTreeLeafPreimage {
static clone(preimage: NullifierLeafPreimage): NullifierLeafPreimage {
return new NullifierLeafPreimage(preimage.nullifier, preimage.nextNullifier, preimage.nextIndex);
}

static fromJSON(json: any): NullifierLeafPreimage {
return new NullifierLeafPreimage(
Fr.fromString(json.nullifier),
Fr.fromString(json.nextNullifier),
BigInt(json.nextIndex),
);
}
}

/**
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/end-to-end/src/e2e_deploy_contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,8 @@ describe('e2e_deploy_contract', () => {
testDeployingAnInstance('from a contract', async instance => {
// Register the instance to be deployed in the pxe
await wallet.addContracts([{ artifact, instance }]);
// Set up the contract that calls the deployer (which happens to be the StatefulTestContract) and call it
const deployer = await registerContract(wallet, TestContract, [accounts[0].address, 48]);
// Set up the contract that calls the deployer (which happens to be the TestContract) and call it
const deployer = await TestContract.deploy(wallet).send().deployed();
await deployer.methods.deploy_contract(instance.address).send().wait();
});
});
Expand Down
Loading
Loading