Skip to content

Commit

Permalink
feat: Add deploy contract helper to aztec-nr (#4775)
Browse files Browse the repository at this point in the history
Adds a helper function to the aztec-nr library to call the contract
instance deployer from another contract. This required adding a new
oracle call to get a full contract instance, as well as enshrining the
deployer contract address as a constant.

Built on #4497
  • Loading branch information
spalladino committed Feb 27, 2024
1 parent 1cb6396 commit 6018fc6
Show file tree
Hide file tree
Showing 25 changed files with 340 additions and 64 deletions.
8 changes: 4 additions & 4 deletions l1-contracts/slither_output.md
Original file line number Diff line number Diff line change
Expand Up @@ -353,15 +353,15 @@ src/core/messagebridge/Inbox.sol#L148-L153
Impact: Informational
Confidence: Medium
- [ ] ID-41
Variable [Constants.LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L122) is too similar to [Constants.NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L115)
Variable [Constants.LOGS_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L125) is too similar to [Constants.NOTE_HASHES_NUM_BYTES_PER_BASE_ROLLUP](src/core/libraries/ConstantsGen.sol#L118)

src/core/libraries/ConstantsGen.sol#L122
src/core/libraries/ConstantsGen.sol#L125


- [ ] ID-42
Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L102) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L103)
Variable [Constants.L1_TO_L2_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L105) is too similar to [Constants.L2_TO_L1_MESSAGE_LENGTH](src/core/libraries/ConstantsGen.sol#L106)

src/core/libraries/ConstantsGen.sol#L102
src/core/libraries/ConstantsGen.sol#L105


- [ ] ID-43
Expand Down
3 changes: 3 additions & 0 deletions l1-contracts/src/core/libraries/ConstantsGen.sol
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,8 @@ library Constants {
0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99;
uint256 internal constant DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE =
0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631;
uint256 internal constant DEPLOYER_CONTRACT_ADDRESS =
0x0747a20ed0c86035e44ea5606f30de459f40b55c5e82012640aa554546af9044;
uint256 internal constant L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 25;
uint256 internal constant MAX_NOTE_FIELDS_LENGTH = 20;
uint256 internal constant GET_NOTE_ORACLE_RETURN_LENGTH = 23;
Expand All @@ -92,6 +94,7 @@ library Constants {
uint256 internal constant CALL_CONTEXT_LENGTH = 8;
uint256 internal constant CONTENT_COMMITMENT_LENGTH = 7;
uint256 internal constant CONTRACT_DEPLOYMENT_DATA_LENGTH = 6;
uint256 internal constant CONTRACT_INSTANCE_LENGTH = 6;
uint256 internal constant CONTRACT_STORAGE_READ_LENGTH = 2;
uint256 internal constant CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2;
uint256 internal constant ETH_ADDRESS_LENGTH = 1;
Expand Down
38 changes: 38 additions & 0 deletions noir-projects/aztec-nr/aztec/src/deploy.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
use crate::{
context::PrivateContext,
oracle::get_contract_instance::get_contract_instance,
};

use dep::protocol_types::{
address::AztecAddress,
abis::function_selector::FunctionSelector,
constants::DEPLOYER_CONTRACT_ADDRESS,
};

// Calls `deploy` on the deployer contract to deploy a new instance.
pub fn deploy_contract(context: &mut PrivateContext, target: AztecAddress) {
let instance = get_contract_instance(target);

let mut universal_deploy = false;
if ! instance.deployer.is_zero() {
assert(instance.deployer == context.this_address(), "Deployer address does not match current address");
universal_deploy = true;
}

// Adapted from noir-contracts/contracts/contract_instance_deployer_contract/src/interface/ContractInstanceDeployer.nr
// That file was autogenerated running the following command from noir-projects/noir-contracts:
// ../../yarn-project/node_modules/.bin/aztec-cli codegen target/contract_instance_deployer_contract-ContractInstanceDeployer.json --nr -o ./contracts/contract_instance_deployer_contract/src/interface
let mut serialized_args = [0; 6];
serialized_args[0] = instance.salt;
serialized_args[1] = instance.contract_class_id.to_field();
serialized_args[2] = instance.initialization_hash;
serialized_args[3] = instance.portal_contract_address.to_field();
serialized_args[4] = instance.public_keys_hash.to_field();
serialized_args[5] = universal_deploy as Field;

let _call_result = context.call_private_function(
AztecAddress::from_field(DEPLOYER_CONTRACT_ADDRESS),
FunctionSelector::from_field(0x883355ab),
serialized_args
);
}
1 change: 1 addition & 0 deletions noir-projects/aztec-nr/aztec/src/lib.nr
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
mod avm;
mod context;
mod deploy;
mod hash;
mod hasher;
mod history;
Expand Down
1 change: 1 addition & 0 deletions noir-projects/aztec-nr/aztec/src/oracle.nr
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ mod arguments;
mod call_private_function;
mod context;
mod debug_log;
mod get_contract_instance;
mod get_l1_to_l2_message;
mod get_nullifier_membership_witness;
mod get_public_data_witness;
Expand Down
14 changes: 14 additions & 0 deletions noir-projects/aztec-nr/aztec/src/oracle/get_contract_instance.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
use dep::protocol_types::{address::AztecAddress, contract_instance::ContractInstance, constants::CONTRACT_INSTANCE_LENGTH};

#[oracle(getContractInstance)]
fn get_contract_instance_oracle(_address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {}

unconstrained fn get_contract_instance_internal(address: AztecAddress) -> [Field; CONTRACT_INSTANCE_LENGTH] {
get_contract_instance_oracle(address)
}

pub fn get_contract_instance(address: AztecAddress) -> ContractInstance {
let instance = ContractInstance::deserialize(get_contract_instance_internal(address));
assert(instance.to_address().eq(address));
instance
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/* Autogenerated file, do not edit! */

use dep::std;
use dep::aztec::context::{PrivateContext, PublicContext};
use dep::aztec::protocol_types::{address::AztecAddress, abis::function_selector::FunctionSelector, constants::RETURN_VALUES_LENGTH};

struct ContractClassIdDeployStruct {
inner: Field,
}

struct PortalContractAddressDeployStruct {
inner: Field,
}

struct PublicKeysHashDeployStruct {
inner: Field,
}

// Interface for calling ContractInstanceDeployer functions from a private context
struct ContractInstanceDeployerPrivateContextInterface {
address: AztecAddress,
}

impl ContractInstanceDeployerPrivateContextInterface {
pub fn at(address: AztecAddress) -> Self {
Self { address }
}

pub fn deploy(
self,
context: &mut PrivateContext,
salt: Field,
contract_class_id: ContractClassIdDeployStruct,
initialization_hash: Field,
portal_contract_address: PortalContractAddressDeployStruct,
public_keys_hash: PublicKeysHashDeployStruct,
universal_deploy: bool
) -> [Field; RETURN_VALUES_LENGTH] {
let mut serialized_args = [0; 6];
serialized_args[0] = salt;
serialized_args[1] = contract_class_id.inner;
serialized_args[2] = initialization_hash;
serialized_args[3] = portal_contract_address.inner;
serialized_args[4] = public_keys_hash.inner;
serialized_args[5] = universal_deploy as Field;

context.call_private_function(
self.address,
FunctionSelector::from_field(0x883355ab),
serialized_args
)
}
}

// Interface for calling ContractInstanceDeployer functions from a public context
struct ContractInstanceDeployerPublicContextInterface {
address: AztecAddress,
}

impl ContractInstanceDeployerPublicContextInterface {
pub fn at(address: AztecAddress) -> Self {
Self { address }
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@ contract StatefulTest {
use dep::std::option::Option;
use dep::value_note::{balance_utils, utils::{increment, decrement}, value_note::{VALUE_NOTE_LEN, ValueNote}};
use dep::aztec::{
deploy::{deploy_contract as aztec_deploy_contract},
context::{PrivateContext, PublicContext, Context},
note::{note_header::NoteHeader, utils as note_utils},
state_vars::{Map, PublicMutable, PrivateSet}
state_vars::{Map, PublicMutable, PrivateSet},
oracle::get_contract_instance::get_contract_instance
};

struct Storage {
Expand Down Expand Up @@ -55,4 +57,10 @@ contract StatefulTest {
unconstrained fn get_public_value(owner: AztecAddress) -> pub Field {
storage.public_values.at(owner).read()
}

// This method is here because we've hit the 32 function limit for the TestContract
#[aztec(private)]
fn deploy_contract(target: AztecAddress) {
aztec_deploy_contract(&mut context, target);
}
}
1 change: 1 addition & 0 deletions noir-projects/noir-protocol-circuits/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
"build": "yarn clean && yarn noir:build",
"clean": "rm -rf ./dest src/target",
"noir:build": "cd src && ../../../noir/target/release/nargo compile --silence-warnings",
"noir:format": "cd src && ../../../noir/target/release/nargo fmt",
"test": "cd src && ../../../noir/target/release/nargo test --silence-warnings"
},
"files": [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ impl Deserialize<1> for PublicKeysHash {
}
}

impl Eq for PublicKeysHash {
fn eq(self, other: Self) -> bool {
self.inner == other.inner
}
}

impl PublicKeysHash {
pub fn from_field(field: Field) -> Self {
Self { inner: field }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,7 @@ global REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE = 0xe7af8166354
// CONTRACT INSTANCE CONSTANTS
// sha224sum 'struct ContractInstanceDeployed'
global DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE = 0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631;
global DEPLOYER_CONTRACT_ADDRESS = 0x0747a20ed0c86035e44ea5606f30de459f40b55c5e82012640aa554546af9044;

// 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.
Expand All @@ -142,6 +143,7 @@ global AZTEC_ADDRESS_LENGTH = 1;
global CALL_CONTEXT_LENGTH: u64 = 8;
global CONTENT_COMMITMENT_LENGTH: u64 = 7;
global CONTRACT_DEPLOYMENT_DATA_LENGTH: u64 = 6;
global CONTRACT_INSTANCE_LENGTH: u64 = 6;
global CONTRACT_STORAGE_READ_LENGTH: u64 = 2;
global CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH: u64 = 2;
global ETH_ADDRESS_LENGTH = 1;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
use crate::{
address::{
aztec_address::AztecAddress, eth_address::EthAddress, partial_address::PartialAddress,
public_keys_hash::PublicKeysHash
},
contract_class_id::ContractClassId,
constants::{GENERATOR_INDEX__CONTRACT_DEPLOYMENT_DATA, CONTRACT_INSTANCE_LENGTH},
traits::{Deserialize, Hash, Serialize}
};

struct ContractInstance {
salt : Field,
deployer: AztecAddress,
contract_class_id : ContractClassId,
initialization_hash : Field,
portal_contract_address : EthAddress,
public_keys_hash : PublicKeysHash,
}

impl Eq for ContractInstance {
fn eq(self, other: Self) -> bool {
self.public_keys_hash.eq(other.public_keys_hash) &
self.initialization_hash.eq(other.initialization_hash) &
self.contract_class_id.eq(other.contract_class_id) &
self.salt.eq(other.salt) &
self.portal_contract_address.eq(other.portal_contract_address)
}
}

impl Serialize<CONTRACT_INSTANCE_LENGTH> for ContractInstance {
fn serialize(self) -> [Field; CONTRACT_INSTANCE_LENGTH] {
[
self.salt,
self.deployer.to_field(),
self.contract_class_id.to_field(),
self.initialization_hash,
self.portal_contract_address.to_field(),
self.public_keys_hash.to_field()
]
}
}

impl Deserialize<CONTRACT_INSTANCE_LENGTH> for ContractInstance {
fn deserialize(serialized: [Field; CONTRACT_INSTANCE_LENGTH]) -> Self {
Self {
salt: serialized[0],
deployer: AztecAddress::from_field(serialized[1]),
contract_class_id: ContractClassId::from_field(serialized[2]),
initialization_hash: serialized[3],
portal_contract_address: EthAddress::from_field(serialized[4]),
public_keys_hash: PublicKeysHash::from_field(serialized[5]),
}
}
}

impl Hash for ContractInstance {
fn hash(self) -> Field {
self.to_address().to_field()
}
}

impl ContractInstance {
fn to_address(self) -> AztecAddress {
AztecAddress::compute(
self.public_keys_hash,
PartialAddress::compute(
self.contract_class_id,
self.salt,
self.initialization_hash,
self.portal_contract_address
)
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ mod transaction;
mod abis;
mod constants;
mod contract_class_id;
mod contract_instance;

mod messaging;
mod mocked;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,8 @@ mod read_requests;
use crate::{
abis::{append_only_tree_snapshot::AppendOnlyTreeSnapshot, global_variables::GlobalVariables},
address::{AztecAddress, EthAddress}, constants::NUM_FIELDS_PER_SHA256,
grumpkin_point::GrumpkinPoint,
content_commitment::ContentCommitment,
header::Header,
partial_state_reference::PartialStateReference,
state_reference::StateReference,
tests::fixtures
grumpkin_point::GrumpkinPoint, content_commitment::ContentCommitment, header::Header,
partial_state_reference::PartialStateReference, state_reference::StateReference, tests::fixtures
};

global MSG_SENDER = AztecAddress { inner: 27 };
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 @@ -69,6 +69,7 @@ export const REGISTERER_UNCONSTRAINED_FUNCTION_BROADCASTED_MAGIC_VALUE =
0xe7af816635466f128568edb04c9fa024f6c87fb9010fdbffa68b3d99n;
export const DEPLOYER_CONTRACT_INSTANCE_DEPLOYED_MAGIC_VALUE =
0x85864497636cf755ae7bde03f267ce01a520981c21c3682aaf82a631n;
export const DEPLOYER_CONTRACT_ADDRESS = 0x0747a20ed0c86035e44ea5606f30de459f40b55c5e82012640aa554546af9044n;
export const L1_TO_L2_MESSAGE_ORACLE_CALL_LENGTH = 25;
export const MAX_NOTE_FIELDS_LENGTH = 20;
export const GET_NOTE_ORACLE_RETURN_LENGTH = 23;
Expand All @@ -78,6 +79,7 @@ export const AZTEC_ADDRESS_LENGTH = 1;
export const CALL_CONTEXT_LENGTH = 8;
export const CONTENT_COMMITMENT_LENGTH = 7;
export const CONTRACT_DEPLOYMENT_DATA_LENGTH = 6;
export const CONTRACT_INSTANCE_LENGTH = 6;
export const CONTRACT_STORAGE_READ_LENGTH = 2;
export const CONTRACT_STORAGE_UPDATE_REQUEST_LENGTH = 2;
export const ETH_ADDRESS_LENGTH = 1;
Expand Down
Loading

0 comments on commit 6018fc6

Please sign in to comment.