diff --git a/docs/docs/developers/tutorials/writing_private_voting_contract.md b/docs/docs/developers/tutorials/writing_private_voting_contract.md index cf69867fe266..f64a16526e8a 100644 --- a/docs/docs/developers/tutorials/writing_private_voting_contract.md +++ b/docs/docs/developers/tutorials/writing_private_voting_contract.md @@ -95,26 +95,10 @@ In this contract, we will store three vars: The next step is to initialize the contract with a constructor. The constructor will take an address as a parameter and set the admin. -All constructors must be private, and because the admin is in public storage, we cannot directly update it from the constructor. You can find more information about this [here](../../learn/concepts/communication/public_private_calls/main.md). - -Therefore our constructor must call a public function by using `context.call_public_function()`. Paste this under the `impl` storage block: - #include_code constructor noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr rust -`context.call_public_function()` takes three arguments: - -1. The contract address whose method we want to call -2. The selector of the function to call (we can use `FunctionSelector::from_signature(...)` for this) -3. The arguments of the function (we pass the `admin`) - -We now need to write the `_initialize()` function: - -#include_code initialize noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr rust - This function takes the admin argument and writes it to the storage. We are also using this function to set the `voteEnded` boolean as false in the same way. -This function is set as `internal` so that it can only be called from within the contract. This stops anyone from setting a new admin. - ## Casting a vote privately For the sake of simplicity, we will have three requirements: diff --git a/docs/docs/developers/tutorials/writing_token_contract.md b/docs/docs/developers/tutorials/writing_token_contract.md index 7ca4f4c7b429..897ef26f9717 100644 --- a/docs/docs/developers/tutorials/writing_token_contract.md +++ b/docs/docs/developers/tutorials/writing_token_contract.md @@ -244,12 +244,10 @@ Copy and paste the body of each function into the appropriate place in your proj ### Constructor -In the source code, the constructor logic is commented out due to some limitations of the current state of the development. +This function sets the creator of the contract (passed as `msg_sender` from the constructor) as the admin and makes them a minter, and sets name, symbol, and decimals. #include_code constructor /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust -The constructor is a private function. There isn't any private state to set up in this function, but there is public state to set up. The `context` is a global variable that is available to private and public functions, but the available methods differ based on the context. You can see the implementation details [here](https://github.com/AztecProtocol/aztec-packages/blob/#include_aztec_version/noir-projects/aztec-nr/aztec/src/context.nr). The `context.call_public_function` allows a private function to call a public function on any contract. In this case, the constructor is passing the `msg_sender` as the argument to the `_initialize` function, which is also defined in this contract. - ### Public function implementations Public functions are declared with the `#[aztec(public)]` macro above the function name like so: @@ -375,14 +373,6 @@ After initializing storage, the function checks that the `msg_sender` is authori Internal functions are functions that can only be called by this contract. The following 3 functions are public functions that are called from the [private execution context](#execution-contexts). Marking these as `internal` ensures that only the desired private functions in this contract are able to call them. Private functions defer execution to public functions because private functions cannot update public state directly. -#### `_initialize` - -This function is called via the [constructor](#constructor). - -This function sets the creator of the contract (passed as `msg_sender` from the constructor) as the admin and makes them a minter. - -#include_code initialize /noir-projects/noir-contracts/contracts/token_contract/src/main.nr rust - #### `_increase_public_balance` This function is called from [`unshield`](#unshield). The account's private balance is decremented in `shield` and the public balance is increased in this function. diff --git a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr index f983dbf38369..096d299bfd56 100644 --- a/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/app_subscription_contract/src/main.nr @@ -31,25 +31,6 @@ contract AppSubscription { global SUBSCRIPTION_TXS = 5; // global GAS_TOKEN_ADDRESS = AztecAddress::from_field(0x08c0e8041f92758ca49ccb62a77318b46090019d380552ddaec5cd0b54804636); - // Constructs the contract - #[aztec(private)] - #[aztec(initializer)] - fn constructor( - target_address: AztecAddress, - subscription_recipient_address: AztecAddress, - subscription_token_address: AztecAddress, - subscription_price: Field, - gas_token_address: AztecAddress - ) { - context.call_public_function( - context.this_address(), - FunctionSelector::from_signature("init((Field),(Field),(Field),Field,(Field))"), - [ - target_address.to_field(), subscription_token_address.to_field(), subscription_recipient_address.to_field(), subscription_price, gas_token_address.to_field() - ] - ); - } - #[aztec(private)] fn entrypoint(payload: pub DAppPayload, user_address: pub AztecAddress) { assert(context.msg_sender().to_field() == 0); @@ -86,12 +67,11 @@ contract AppSubscription { } #[aztec(public)] - #[aztec(internal)] - #[aztec(noinitcheck)] - fn init( + #[aztec(initializer)] + fn constructor( target_address: AztecAddress, - subscription_token_address: AztecAddress, subscription_recipient_address: AztecAddress, + subscription_token_address: AztecAddress, subscription_price: Field, gas_token_address: AztecAddress ) { diff --git a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr index 60cbf894ef18..8417feced27a 100644 --- a/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/easy_private_voting_contract/src/main.nr @@ -15,26 +15,14 @@ contract EasyPrivateVoting { // docs:end:storage_struct // docs:start:constructor - #[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) - context.this_address(),// contract address whose method we want to call - FunctionSelector::from_signature("_initialize((Field))"), // function selector - [admin.to_field()] // parameters - ); - } - // docs:end:constructor - // docs:start:initialize - #[aztec(public)] // annotation to mark function as public and expose public context - #[aztec(internal)] // internal - can only be called by contract - #[aztec(noinitcheck)] - fn _initialize(admin: AztecAddress) { + #[aztec(public)] + #[aztec(initializer)] // annotation to mark function as a constructor + fn constructor(admin: AztecAddress) { storage.admin.write(admin); storage.voteEnded.write(false); } - // docs:end:initialize + // docs:end:constructor + // docs:start:cast_vote #[aztec(private)] // annotation to mark function as private and expose private context fn cast_vote(candidate: Field) { diff --git a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr index 7207f0ef308e..a69c4d0bdabc 100644 --- a/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/fpc_contract/src/main.nr @@ -11,21 +11,9 @@ contract FPC { fee_asset: SharedImmutable, } - #[aztec(private)] + #[aztec(public)] #[aztec(initializer)] fn constructor(other_asset: AztecAddress, fee_asset: AztecAddress) { - let selector = FunctionSelector::from_signature("_initialize((Field),(Field))"); - context.call_public_function( - context.this_address(), - selector, - [other_asset.to_field(), fee_asset.to_field()] - ); - } - - #[aztec(public)] - #[aztec(internal)] - #[aztec(noinitcheck)] - fn _initialize(other_asset: AztecAddress, fee_asset: AztecAddress) { storage.other_asset.initialize(other_asset); storage.fee_asset.initialize(fee_asset); } diff --git a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr index b026448a1b09..87f9667582b5 100644 --- a/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/inclusion_proofs_contract/src/main.nr @@ -29,18 +29,10 @@ contract InclusionProofs { public_unused_value: PublicMutable, } - #[aztec(private)] + #[aztec(public)] #[aztec(initializer)] fn constructor(public_value: Field) { - let selector = FunctionSelector::from_signature("_initialize(Field)"); - context.call_public_function(context.this_address(), selector, [public_value]); - } - - #[aztec(public)] - #[aztec(internal)] - #[aztec(noinitcheck)] - fn _initialize(value: Field) { - storage.public_value.write(value); + storage.public_value.write(public_value); } // docs:start:create_note diff --git a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr index 1e26124a5bb2..42b042711ce4 100644 --- a/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_blacklist_contract/src/main.nr @@ -40,16 +40,18 @@ contract TokenBlacklist { } // docs:start:constructor - #[aztec(private)] + #[aztec(public)] #[aztec(initializer)] fn constructor(admin: AztecAddress, slow_updates_contract: AztecAddress) { // docs:end:constructor - let selector = FunctionSelector::from_signature("_initialize((Field),(Field))"); - context.call_public_function( - context.this_address(), - selector, - [admin.to_field(), slow_updates_contract.to_field()] - ); + assert(!admin.is_zero(), "invalid admin"); + storage.admin.write(admin); + // docs:start:write_slow_update_public + storage.slow_update.initialize(slow_updates_contract); + // docs:end:write_slow_update_public + // docs:start:slowmap_initialize + SlowMap::at(slow_updates_contract).initialize(context); + // docs:end:slowmap_initialize // We cannot do the following atm // let roles = UserFlags { is_admin: true, is_minter: false, is_blacklisted: false }.get_value().to_field(); // SlowMap::at(slow_updates_contract).update_at_private(&mut context, admin.to_field(), roles); @@ -75,21 +77,6 @@ contract TokenBlacklist { assert(storage.admin.read().eq(caller), "caller is not admin"); } - /////// - #[aztec(public)] - #[aztec(internal)] - #[aztec(noinitcheck)] - fn _initialize(new_admin: AztecAddress, slow_updates_contract: AztecAddress) { - assert(!new_admin.is_zero(), "invalid admin"); - storage.admin.write(new_admin); - // docs:start:write_slow_update_public - storage.slow_update.initialize(slow_updates_contract); - // docs:end:write_slow_update_public - // docs:start:slowmap_initialize - SlowMap::at(slow_updates_contract).initialize(context); - // docs:end:slowmap_initialize - } - #[aztec(private)] fn update_roles(user: AztecAddress, roles: Field) { // docs:start:slowmap_at diff --git a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr index ed6ff0dfceb9..5b8ed0086878 100644 --- a/noir-projects/noir-contracts/contracts/token_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/token_contract/src/main.nr @@ -52,17 +52,17 @@ contract Token { // docs:end:storage_struct // docs:start:constructor - #[aztec(private)] + #[aztec(public)] #[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); - let symbol_s = FieldCompressedString::from_string(symbol); - context.call_public_function( - context.this_address(), - selector, - [admin.to_field(), name_s.serialize()[0], symbol_s.serialize()[0], decimals as Field] - ); + assert(!admin.is_zero(), "invalid admin"); + storage.admin.write(admin); + storage.minters.at(admin).write(true); + storage.name.initialize(FieldCompressedString::from_string(name)); + storage.symbol.initialize(FieldCompressedString::from_string(symbol)); + // docs:start:initialize_decimals + storage.decimals.initialize(decimals); + // docs:end:initialize_decimals } // docs:end:constructor @@ -311,27 +311,6 @@ contract Token { } // docs:end:burn - // docs:start:initialize - #[aztec(public)] - #[aztec(internal)] - #[aztec(noinitcheck)] - fn _initialize( - new_admin: AztecAddress, - name: FieldCompressedString, - symbol: FieldCompressedString, - decimals: u8 - ) { - assert(!new_admin.is_zero(), "invalid admin"); - storage.admin.write(new_admin); - storage.minters.at(new_admin).write(true); - storage.name.initialize(name); - storage.symbol.initialize(symbol); - // docs:start:initialize_decimals - storage.decimals.initialize(decimals); - // docs:end:initialize_decimals - } - // docs:end:initialize - /// Internal /// // docs:start:increase_public_balance diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr index bd27c381283a..0d1b854a0809 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/common.nr @@ -33,9 +33,6 @@ pub fn validate_inputs(public_call: PublicCallData) { !this_call_stack_item.contract_address.eq(AztecAddress::zero()), "Contract address cannot be zero" ); assert(this_call_stack_item.function_data.selector.to_field() != 0, "Function signature cannot be zero"); - assert( - this_call_stack_item.function_data.is_constructor == false, "Constructors cannot be public functions" - ); assert( this_call_stack_item.function_data.is_private == false, "Cannot execute a private function with the public kernel circuit" ); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr index 7e0df945db17..444c47189f1c 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_setup.nr @@ -199,22 +199,6 @@ mod tests { // assert_eq_public_data_update_requests(public_inputs.end.public_data_update_requests, expected); // } - #[test(should_fail_with="Constructors cannot be public functions")] - fn constructor_should_fail() { - let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - builder.public_call.function_data.is_constructor = true; - - builder.failed(); - } - - #[test(should_fail_with="Contract deployment cannot be a public function")] - fn constructor_should_fail_2() { - let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); - builder.public_call.public_inputs.call_context.is_contract_deployment = true; - - builder.failed(); - } - #[test(should_fail_with="Bytecode hash cannot be zero")] fn no_bytecode_hash_should_fail() { let mut builder = PublicKernelSetupCircuitPrivateInputsBuilder::new(); diff --git a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr index 7139187956c8..6460db3d1081 100644 --- a/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr +++ b/noir-projects/noir-protocol-circuits/crates/public-kernel-lib/src/public_kernel_teardown.nr @@ -143,22 +143,6 @@ mod tests { } } - #[test(should_fail_with="Constructors cannot be public functions")] - fn constructor_should_fail() { - let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - builder.public_call.function_data.is_constructor = true; - - builder.failed(); - } - - #[test(should_fail_with="Contract deployment cannot be a public function")] - fn constructor_should_fail_2() { - let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new(); - builder.public_call.public_inputs.call_context.is_contract_deployment = true; - - builder.failed(); - } - #[test(should_fail_with="Bytecode hash cannot be zero")] fn no_bytecode_hash_should_fail() { let mut builder = PublicKernelTeardownCircuitPrivateInputsBuilder::new();