Skip to content

Commit 43aa603

Browse files
authored
feat: contract inclusion proof (AztecProtocol#3680)
1. Fixes AztecProtocol#3465 2. Fixes AztecProtocol#3695 3. naming consistency fix in get sibling path methods, 4. refactored the e2e test and each type of proof is now in a nested describe statement.
1 parent c7b29b3 commit 43aa603

File tree

12 files changed

+368
-142
lines changed

12 files changed

+368
-142
lines changed

yarn-project/aztec-node/src/aztec-node/server.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ export class AztecNodeService implements AztecNode {
339339
* @param leafIndex - The index of the leaf for which the sibling path is required.
340340
* @returns The sibling path for the leaf index.
341341
*/
342-
public async getNullifierTreeSiblingPath(
342+
public async getNullifierSiblingPath(
343343
blockNumber: number | 'latest',
344344
leafIndex: bigint,
345345
): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>> {
@@ -408,7 +408,7 @@ export class AztecNodeService implements AztecNode {
408408
* @param leafIndex - Index of the leaf in the tree.
409409
* @returns The sibling path.
410410
*/
411-
public async getPublicDataTreeSiblingPath(
411+
public async getPublicDataSiblingPath(
412412
blockNumber: number | 'latest',
413413
leafIndex: bigint,
414414
): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>> {

yarn-project/aztec-nr/aztec/src/history.nr

+1
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
mod contract_inclusion;
12
mod note_inclusion;
23
mod note_validity;
34
mod nullifier_inclusion;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
use dep::protocol_types::{
2+
abis::{
3+
complete_address::CompleteAddress,
4+
new_contract_data::NewContractData as ContractLeafPreimage,
5+
},
6+
address::{AztecAddress, EthAddress},
7+
point::Point,
8+
};
9+
use dep::std::merkle::compute_merkle_root;
10+
11+
use crate::{
12+
context::PrivateContext,
13+
oracle::get_membership_witness::get_contract_membership_witness,
14+
};
15+
16+
// Proves that a contract exists at block `block_number` and returns its address.
17+
// Note: This can be used to approximate a factory pattern --> a factory contract could perform this proof and that
18+
// way verify that a contract at a given address is what it expects. Then it could store it in an internal
19+
// map of contracts (like what Uniswap Factory does with pool contracts - it stores them in a mapping).
20+
// By passing in the construct hash the factory can also verify that the contract was constructed with the
21+
// correct constructor arguments. Typically the factory would store the expected construct hash and assert that
22+
// it is what it expects. The constructor param check is the reason of why we pass in the preimage of contract's
23+
// aztec address instead of just the address.
24+
pub fn prove_contract_inclusion(
25+
deployer_public_key: Point,
26+
contract_address_salt: Field,
27+
function_tree_root: Field,
28+
constructor_hash: Field,
29+
portal_contract_address: EthAddress,
30+
block_number: u32, // The block at which we'll prove that the public value exists
31+
context: PrivateContext
32+
) -> AztecAddress {
33+
// 1) Get block header from oracle and ensure that the block is included in the archive.
34+
let block_header = context.get_block_header(block_number);
35+
36+
// 2) Compute the contract address
37+
let contract_address = CompleteAddress::compute(
38+
deployer_public_key,
39+
contract_address_salt,
40+
function_tree_root,
41+
constructor_hash
42+
).address;
43+
44+
// 3) Form the contract tree leaf preimage
45+
let preimage = ContractLeafPreimage { contract_address, portal_contract_address, function_tree_root };
46+
47+
// 4) Get the contract tree leaf by hashing the preimage
48+
let contract_leaf = preimage.hash();
49+
50+
// 5) Get the membership witness of the leaf in the contract tree
51+
let witness = get_contract_membership_witness(block_number, contract_leaf);
52+
53+
// 6) Prove that the leaf is in the contract tree
54+
assert(
55+
block_header.contract_tree_root
56+
== compute_merkle_root(contract_leaf, witness.index, witness.path), "Proving contract inclusion failed"
57+
);
58+
59+
// --> Now we have traversed the trees all the way up to archive root.
60+
61+
contract_address
62+
}

yarn-project/aztec.js/src/contract_deployer/deploy_method.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
6969

7070
const { chainId, protocolVersion } = await this.pxe.getNodeInfo();
7171

72-
const { completeAddress, constructorHash, functionTreeRoot } = getContractDeploymentInfo(
72+
const { completeAddress, constructorVkHash, functionTreeRoot } = getContractDeploymentInfo(
7373
this.artifact,
7474
this.args,
7575
contractAddressSalt,
@@ -78,7 +78,7 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas
7878

7979
const contractDeploymentData = new ContractDeploymentData(
8080
this.publicKey,
81-
constructorHash,
81+
constructorVkHash,
8282
functionTreeRoot,
8383
contractAddressSalt,
8484
portalContract,

yarn-project/circuits.js/src/contract/contract_deployment_info.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,8 @@ export function getContractDeploymentInfo(
4848

4949
return {
5050
completeAddress,
51-
constructorHash: constructorVkHash,
51+
constructorHash,
52+
constructorVkHash,
5253
functionTreeRoot,
5354
};
5455
}

yarn-project/circuits.js/src/types/deployment_info.ts

+4
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,10 @@ export type DeploymentInfo = {
88
* The complete address of the deployed contract.
99
*/
1010
completeAddress: CompleteAddress;
11+
/**
12+
* The contract's constructor verification key hash.
13+
*/
14+
constructorVkHash: Fr;
1115
/**
1216
* The contract's constructor hash.
1317
*/

0 commit comments

Comments
 (0)