Skip to content

Commit

Permalink
feat: Instance deployer contract
Browse files Browse the repository at this point in the history
Implementation for the initial contract instance deployer contract.
Skips validations for class id and eth address for now. Pending to
listen to these events on the node.

Builds on #4429
Fixes #4071
  • Loading branch information
spalladino committed Feb 5, 2024
1 parent 3966e7b commit c2f4f11
Show file tree
Hide file tree
Showing 10 changed files with 156 additions and 2 deletions.
2 changes: 2 additions & 0 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@ library Constants {
0x1b70e95fde0b70adc30496b90a327af6a5e383e028e7a43211a07bcd;
uint256 internal constant REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE =
0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99;
uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE =
0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631;
uint256 internal constant L1_TO_L2_MESSAGE_LENGTH = 8;
uint256 internal constant L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 25;
uint256 internal constant MAX_NOTE_FIELDS_LENGTH = 20;
Expand Down
2 changes: 2 additions & 0 deletions yarn-project/circuits.js/src/constants.gen.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export const REGISTERER_PRIVATE_FUNCTION_BROADCASTED_MAGIC_VALUE =
0x1b70e95fde0b70adc30496b90a327af6a5e383e028e7a43211a07bcdn;
export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE =
0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n;
export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE =
0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n;
export const L1_TO_L2_MESSAGE_LENGTH = 8;
export const L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 25;
export const MAX_NOTE_FIELDS_LENGTH = 20;
Expand Down
29 changes: 27 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 @@ -24,18 +24,25 @@ import {
ARTIFACT_FUNCTION_TREE_MAX_HEIGHT,
MAX_PACKED_BYTECODE_SIZE_PER_PRIVATE_FUNCTION_IN_FIELDS,
MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS,
Point,
computeArtifactFunctionTree,
computeArtifactFunctionTreeRoot,
computeArtifactMetadataHash,
computeFunctionArtifactHash,
computePrivateFunctionsRoot,
computePrivateFunctionsTree,
computePublicBytecodeCommitment,
computePublicKeysHash,
} from '@aztec/circuits.js';
import { siloNullifier } from '@aztec/circuits.js/abis';
import { FunctionSelector, FunctionType, bufferAsFields } from '@aztec/foundation/abi';
import { padArrayEnd } from '@aztec/foundation/collection';
import { ContractClassRegistererContract, ReaderContractArtifact, StatefulTestContract } from '@aztec/noir-contracts';
import {
ContractClassRegistererContract,
ContractInstanceDeployerContract,
ReaderContractArtifact,
StatefulTestContract,
} from '@aztec/noir-contracts';
import { TestContract, TestContractArtifact } from '@aztec/noir-contracts/Test';
import { TokenContractArtifact } from '@aztec/noir-contracts/Token';
import { SequencerClient } from '@aztec/sequencer-client';
Expand Down Expand Up @@ -263,7 +270,7 @@ describe('e2e_deploy_contract', () => {

// Tests registering a new contract class on a node
// All this dance will be hidden behind a nicer API in the near future!
describe('registering a new contract class', () => {
describe('public registration and deployment', () => {
let registerer: ContractClassRegistererContract;
let artifact: ContractArtifact;
let contractClass: ContractClassWithId;
Expand Down Expand Up @@ -376,6 +383,24 @@ describe('e2e_deploy_contract', () => {
.send()
.wait();
}, 60_000);

it('deploys a new instance of the registered class via the deployer', async () => {
const deployer = await registerContract(wallet, ContractInstanceDeployerContract, [], new Fr(1));

const salt = Fr.random();
const initArgs = Fr.ZERO;
const portalAddress = EthAddress.random();
const publicKeysHash = computePublicKeysHash(Point.random());

const tx = await deployer.methods
.deploy(salt, contractClass.id, initArgs, portalAddress, publicKeysHash, false)
.send()
.wait();

const logs = await pxe.getUnencryptedLogs({ txHash: tx.txHash });
const deployedLog = logs.logs[0].log;
expect(deployedLog.contractAddress).toEqual(deployer.address);
});
});
});

Expand Down
1 change: 1 addition & 0 deletions yarn-project/noir-contracts/Nargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ members = [
"contracts/card_game_contract",
"contracts/child_contract",
"contracts/contract_class_registerer_contract",
"contracts/contract_instance_deployer_contract",
"contracts/counter_contract",
"contracts/docs_example_contract",
"contracts/easy_private_token_contract",
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
[package]
name = "contract_instance_deployer_contract"
authors = [""]
compiler_version = ">=0.18.0"
type = "contract"

[dependencies]
aztec = { path = "../../../aztec-nr/aztec" }
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mod instance_deployed;
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use dep::aztec::protocol_types::{
contract_class::ContractClassId,
address::{ AztecAddress, EthAddress, PublicKeysHash, PartialAddress },
constants::{DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE},
traits::{Serialize}
};

// #[event]
struct ContractInstanceDeployed {
address: AztecAddress,
version: u8,
salt: Field,
contract_class_id: ContractClassId,
initialization_hash: Field,
portal_contract_address: EthAddress,
public_keys_hash: PublicKeysHash,
universal_deploy: bool,
}

global CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE: Field = 9;

impl Serialize<CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE> for ContractInstanceDeployed {
fn serialize(self: Self) -> [Field; CONTRACT_INSTANCE_DEPLOYED_SERIALIZED_SIZE] {
[
DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE,
self.address.to_field(),
self.version as Field,
self.salt,
self.contract_class_id.to_field(),
self.initialization_hash,
self.portal_contract_address.to_field(),
self.public_keys_hash.to_field(),
self.universal_deploy as Field,
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
mod events;

contract ContractInstanceDeployer {
use dep::std::option::Option;
use dep::aztec::protocol_types::{
address::{ AztecAddress, EthAddress, PublicKeysHash, PartialAddress },
contract_class::ContractClassId,
constants::{DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE},
traits::{Serialize}
};

use dep::aztec::log::{ emit_unencrypted_log, emit_unencrypted_log_from_private};

use crate::events::{
instance_deployed::ContractInstanceDeployed,
};

#[aztec(private)]
fn constructor() {}

#[aztec(private)]
fn deploy(
salt: Field,
contract_class_id: ContractClassId,
initialization_hash: Field,
portal_contract_address: EthAddress,
public_keys_hash: PublicKeysHash,
universal_deploy: bool
) {
// TODO(@spalladino): assert nullifier_exists silo(contract_class_id, ContractClassRegisterer)
// TODO(@spalladino): assert is_valid_eth_address(portal_contract_address)

// TODO(#4434) Add deployer field to instance calculation
// let deployer = if universal_deploy { Field::zero() } else { context.msg_sender() };

let partial_address = PartialAddress::compute(
contract_class_id,
salt,
initialization_hash,
portal_contract_address
);

let address = AztecAddress::compute(public_keys_hash, partial_address);

// Emit the address as a nullifier to be able to prove that this instance has been (not) deployed
context.push_new_nullifier(address.to_field(), 0);

// Broadcast the event
let event = ContractInstanceDeployed {
contract_class_id,
address,
public_keys_hash,
portal_contract_address,
initialization_hash,
salt,
universal_deploy,
version: 1
};
let event_payload = event.serialize();
dep::aztec::oracle::debug_log::debug_log_array_with_prefix("ContractInstanceDeployed", event_payload);
emit_unencrypted_log_from_private(&mut context, event_payload);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,18 @@ impl ToField for PublicKeysHash {
}
}

impl Serialize<1> for PublicKeysHash {
fn serialize(self: Self) -> [Field; 1] {
[self.to_field()]
}
}

impl Deserialize<1> for PublicKeysHash {
fn deserialize(fields: [Field; 1]) -> Self {
PublicKeysHash::from_field(fields[0])
}
}

impl PublicKeysHash {
pub fn from_field(field : Field) -> Self {
Self {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,10 @@ global REGISTERER_PRIVATE_FUNCTION_BROADCASTED_MAGIC_VALUE = 0x1b70e95fde0b70adc
// sha224sum 'struct ClassUnconstrainedFunctionBroadcasted'
global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99;

// CONTRACT INSTANCE CONSTANTS
// sha224sum 'struct ContractInstanceDeployed'
global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631;

// NOIR CONSTANTS - constants used only in yarn-packages/noir-contracts
// Some are defined here because Noir doesn't yet support globals referencing other globals yet.
// Move these constants to a noir file once the issue below is resolved:
Expand Down

0 comments on commit c2f4f11

Please sign in to comment.