Rethinking contract deployment

I wanted to share a brief overview of what we’re building for the new contract deployment scheme for the Aztec Network, most of it based on this thread and outlined on the yellow paper.

Classes and instances

A contract in Aztec will no longer have code of its own. Instead, a contract (or contract instance for clarity) will reference a contract class. Contract classes are just code, referenced by an identifier. Contract classes do not hold any state, and cannot be called. Instead, users interact with instances of each class, at a given address. We expect that this separation at the protocol level will make code reuse easier.

Identifiers as commitments

A contract class identifier is the hash of (ie a commitment to) its code and verification keys. Likewise, a contract address (which is the identifier of a contract instance) is a commitment to its contract class, deployer address, public keys, initialization arguments, etc.

No deployment needed for private calls

Having identifiers as commitments means that, given a contract address, we can prove what functions it implements. So, when executing a private function in a contract, the user (via the private kernel circuit) just needs to prove that:
1- The verification key used for the private function is in the preimage of a contract class C
2- The contract class C is in the preimage of the address being run

This means that we do not need to actually “deploy” a contract in order to call a private function in it, since the address of the contract is already a commitment to its code. This allows us to get rid of the contract tree.

Broadcasting deployments via ClassRegisterer and Deployer contracts

However, for executing public functions, we do need to make sure all nodes have access to the code that needs to be run. Otherwise, we risk having transactions with public calls that not all nodes know how to run. So, in order to run a public function, we require the contract instance and its class to have been broadcasted to the network.

This “broadcasting” today is implemented in-protocol, by having special “contract deployment” transactions. We will be simplifying this by moving this logic up in the stack: instead of having special deployment transactions, we’ll have special “Registerer” and “Deployer” contracts, whose only responsibility will be to:
1- Broadcast via unencrypted events a contract class or a contract instance
2- Emit a nullifier to signal that they have been broadcasted

The nullifier allows an Aztec node (via its public kernel circuit) to prove that the code for a given address is known or not. If it is not known, the sequencer can generate a nullifier non-membership proof to provably revert the associated tx.

Initialization at the application circuit

Constructors will be removed from the protocol level as well. Instead, initializing a contract will be just calling a function that takes care of setting everything up, and then emits an “initialization nullifier” so the contract cannot be initialized again. All other functions in a contract should check that the initialization nullifier has been emitted in order to avoid being called before the contract is initialized. The plan is to handle all this logic under the hood using macros.

Removing constructors from the protocol gives us more flexibility on how to initialize a contract. Now we can have both private and public constructors, or multiple constructor functions per contract, or call a constructor from another contract, or initialize multiple contracts in the same tx, or not have a constructor at all if we don’t need it, or have functions that don’t require the contract to be initialized in order to be executed.

Summing up

  • Contracts are split into classes and instances, where a class may have multiple instances.
  • You can call a private function in any contract without having to deploy it, allowing fully private contracts between small parties.
  • But you need to “broadcast” it to call public functions on it.
  • Initializing a contract is just calling a function that can be called only once.

The information set out herein is for discussion purposes only and does not represent any binding indication or commitment by Aztec Labs and its employees to take any action whatsoever, including relating to the structure and/or any potential operation of the Aztec protocol or the protocol roadmap. In particular: (i) nothing in these posts is intended to create any contractual or other form of legal relationship with Aztec Labs or third parties who engage with such posts (including, without limitation, by submitting a proposal or responding to posts), (ii) by engaging with any post, the relevant persons are consenting to Aztec Labs’ use and publication of such engagement and related information on an open-source basis (and agree that Aztec Labs will not treat such engagement and related information as confidential), and (iii) Aztec Labs is not under any duty to consider any or all engagements, and that consideration of such engagements and any decision to award grants or other rewards for any such engagement is entirely at Aztec Labs’ sole discretion. Please do not rely on any information on this forum for any purpose - the development, release, and timing of any products, features or functionality remains subject to change and is currently entirely hypothetical. Nothing on this forum should be treated as an offer to sell any security or any other asset by Aztec Labs or its affiliates, and you should not rely on any forum posts or content for advice of any kind, including legal, investment, financial, tax or other professional advice.”


@ spalladino
Thank you, this article is very useful, especially for those who want to better understand how the Aztec protocol works

@Sanemi I know you were looking for something like that :blush:

and I think this will be interesting for you

especially this one

Blockquote From the hackmd:

The first reply