-
Notifications
You must be signed in to change notification settings - Fork 607
feat: contract inclusion proof #3680
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
b378931
4bf6b27
2bf06d7
1b88d1d
d4da60d
40ec8a3
3485b03
bdbaf9c
9237488
1f878be
9563410
c6483ae
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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; | ||
|
|
||
| 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 | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
|
@@ -78,7 +78,7 @@ export class DeployMethod<TContract extends ContractBase = Contract> extends Bas | |
|
|
||
| const contractDeploymentData = new ContractDeploymentData( | ||
| this.publicKey, | ||
| constructorHash, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. For my mental image, it still made more sense to me that it was the constructor hash actually combining all the things and not just the vk hash. Bu as @iAmMichaelConnor mentioned they he desire to change how contracts are deployed anyway, don't seem worth it to look deeper into that now.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Maybe I misunderstood but the constructor hash is actually "combining all the things" since part of its preimage is the constructor vk hash (see this code). This change I did didn't break anything because wherever the incorrectly named constructorHash value was used it actually represented the constructorVkHash. Here is where the value is assigned. |
||
| constructorVkHash, | ||
| functionTreeRoot, | ||
| contractAddressSalt, | ||
| portalContract, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.