Skip to content

Commit

Permalink
feat: contract inclusion proof (#3680)
Browse files Browse the repository at this point in the history
1. Fixes #3465
2. Fixes #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.
  • Loading branch information
benesjan authored Dec 15, 2023
1 parent c7b29b3 commit 43aa603
Show file tree
Hide file tree
Showing 12 changed files with 368 additions and 142 deletions.
4 changes: 2 additions & 2 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ export class AztecNodeService implements AztecNode {
* @param leafIndex - The index of the leaf for which the sibling path is required.
* @returns The sibling path for the leaf index.
*/
public async getNullifierTreeSiblingPath(
public async getNullifierSiblingPath(
blockNumber: number | 'latest',
leafIndex: bigint,
): Promise<SiblingPath<typeof NULLIFIER_TREE_HEIGHT>> {
Expand Down Expand Up @@ -408,7 +408,7 @@ export class AztecNodeService implements AztecNode {
* @param leafIndex - Index of the leaf in the tree.
* @returns The sibling path.
*/
public async getPublicDataTreeSiblingPath(
public async getPublicDataSiblingPath(
blockNumber: number | 'latest',
leafIndex: bigint,
): Promise<SiblingPath<typeof PUBLIC_DATA_TREE_HEIGHT>> {
Expand Down
1 change: 1 addition & 0 deletions yarn-project/aztec-nr/aztec/src/history.nr
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod contract_inclusion;
mod note_inclusion;
mod note_validity;
mod nullifier_inclusion;
Expand Down
62 changes: 62 additions & 0 deletions yarn-project/aztec-nr/aztec/src/history/contract_inclusion.nr
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use dep::protocol_types::{
abis::{
complete_address::CompleteAddress,
new_contract_data::NewContractData as ContractLeafPreimage,
},
address::{AztecAddress, EthAddress},
point::Point,
};
use dep::std::merkle::compute_merkle_root;

use crate::{
context::PrivateContext,
oracle::get_membership_witness::get_contract_membership_witness,
};

// Proves that a contract exists at block `block_number` and returns its address.
// Note: This can be used to approximate a factory pattern --> a factory contract could perform this proof and that
// way verify that a contract at a given address is what it expects. Then it could store it in an internal
// map of contracts (like what Uniswap Factory does with pool contracts - it stores them in a mapping).
// By passing in the construct hash the factory can also verify that the contract was constructed with the
// correct constructor arguments. Typically the factory would store the expected construct hash and assert that
// it is what it expects. The constructor param check is the reason of why we pass in the preimage of contract's
// aztec address instead of just the address.
pub fn prove_contract_inclusion(
deployer_public_key: Point,
contract_address_salt: Field,
function_tree_root: Field,
constructor_hash: Field,
portal_contract_address: EthAddress,
block_number: u32, // The block at which we'll prove that the public value exists
context: PrivateContext
) -> AztecAddress {
// 1) Get block header from oracle and ensure that the block is included in the archive.
let block_header = context.get_block_header(block_number);

// 2) Compute the contract address
let contract_address = CompleteAddress::compute(
deployer_public_key,
contract_address_salt,
function_tree_root,
constructor_hash
).address;

// 3) Form the contract tree leaf preimage
let preimage = ContractLeafPreimage { contract_address, portal_contract_address, function_tree_root };

// 4) Get the contract tree leaf by hashing the preimage
let contract_leaf = preimage.hash();

// 5) Get the membership witness of the leaf in the contract tree
let witness = get_contract_membership_witness(block_number, contract_leaf);

// 6) Prove that the leaf is in the contract tree
assert(
block_header.contract_tree_root
== compute_merkle_root(contract_leaf, witness.index, witness.path), "Proving contract inclusion failed"
);

// --> Now we have traversed the trees all the way up to archive root.

contract_address
}
4 changes: 2 additions & 2 deletions yarn-project/aztec.js/src/contract_deployer/deploy_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas

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

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

const contractDeploymentData = new ContractDeploymentData(
this.publicKey,
constructorHash,
constructorVkHash,
functionTreeRoot,
contractAddressSalt,
portalContract,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,8 @@ export function getContractDeploymentInfo(

return {
completeAddress,
constructorHash: constructorVkHash,
constructorHash,
constructorVkHash,
functionTreeRoot,
};
}
4 changes: 4 additions & 0 deletions yarn-project/circuits.js/src/types/deployment_info.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,10 @@ export type DeploymentInfo = {
* The complete address of the deployed contract.
*/
completeAddress: CompleteAddress;
/**
* The contract's constructor verification key hash.
*/
constructorVkHash: Fr;
/**
* The contract's constructor hash.
*/
Expand Down
Loading

0 comments on commit 43aa603

Please sign in to comment.