diff --git a/yarn-project/circuit-types/src/contract_dao.test.ts b/yarn-project/circuit-types/src/contract_dao.test.ts deleted file mode 100644 index e8bfe08be0c..00000000000 --- a/yarn-project/circuit-types/src/contract_dao.test.ts +++ /dev/null @@ -1,56 +0,0 @@ -import { ABIParameterVisibility, ContractArtifact, FunctionSelector, FunctionType } from '@aztec/foundation/abi'; - -import { ContractDao } from './contract_dao.js'; -import { randomContractArtifact, randomContractInstanceWithAddress } from './mocks.js'; - -describe('ContractDao', () => { - it('serializes / deserializes correctly', () => { - const artifact = randomContractArtifact(); - const dao = new ContractDao(artifact, randomContractInstanceWithAddress()); - - expect(ContractDao.fromBuffer(dao.toBuffer())).toEqual(dao); - }); - - it('extracts function data', () => { - const artifact: ContractArtifact = { - name: 'test', - functions: [ - { - name: 'bar', - isInitializer: false, - functionType: FunctionType.SECRET, - isInternal: false, - parameters: [ - { - name: 'value', - type: { - kind: 'field', - }, - visibility: ABIParameterVisibility.PUBLIC, - }, - { - name: 'value', - type: { - kind: 'field', - }, - visibility: ABIParameterVisibility.SECRET, - }, - ], - returnTypes: [], - bytecode: '0af', - debugSymbols: '', - }, - ], - events: [], - fileMap: {}, - }; - - const dao = new ContractDao(artifact, randomContractInstanceWithAddress()); - - expect(dao.functions[0]).toEqual({ - ...artifact.functions[0], - // number representing bar((Field),Field) - selector: new FunctionSelector(4138634513), - }); - }); -}); diff --git a/yarn-project/circuit-types/src/contract_dao.ts b/yarn-project/circuit-types/src/contract_dao.ts deleted file mode 100644 index b24b45e5515..00000000000 --- a/yarn-project/circuit-types/src/contract_dao.ts +++ /dev/null @@ -1,78 +0,0 @@ -import { AztecAddress, ContractFunctionDao } from '@aztec/circuits.js'; -import { - ContractArtifact, - DebugFileMap, - EventAbi, - FunctionDebugMetadata, - FunctionSelector, - getFunctionDebugMetadata, -} from '@aztec/foundation/abi'; -import { BufferReader, prefixBufferWithLength } from '@aztec/foundation/serialize'; -import { ContractInstanceWithAddress, SerializableContractInstance } from '@aztec/types/contracts'; - -/** - * A contract Data Access Object (DAO). - * Contains the contract's address, portal contract address, and an array of ContractFunctionDao objects. - * Each ContractFunctionDao object includes FunctionAbi data and the function selector buffer. - */ -export class ContractDao implements ContractArtifact { - /** An array of contract functions with additional selector property. */ - public readonly functions: ContractFunctionDao[]; - - constructor(private contractArtifact: ContractArtifact, public readonly instance: ContractInstanceWithAddress) { - this.functions = contractArtifact.functions.map(f => ({ - ...f, - selector: FunctionSelector.fromNameAndParameters(f.name, f.parameters), - })); - } - - get aztecNrVersion() { - return this.contractArtifact.aztecNrVersion; - } - - get name(): string { - return this.contractArtifact.name; - } - - get events(): EventAbi[] { - return this.contractArtifact.events; - } - - get fileMap(): DebugFileMap { - return this.contractArtifact.fileMap; - } - - getFunctionArtifact(selector: FunctionSelector): ContractFunctionDao | undefined { - return this.functions.find(f => f.selector.equals(selector)); - } - - getFunctionArtifactByName(functionName: string): ContractFunctionDao | undefined { - return this.functions.find(f => f.name === functionName); - } - - getFunctionDebugMetadataByName(functionName: string): FunctionDebugMetadata | undefined { - const fn = this.getFunctionArtifactByName(functionName); - return fn && getFunctionDebugMetadata(this, fn); - } - - toBuffer(): Buffer { - // the contract artifact was originally emitted to a JSON file by Noir - // should be safe to JSON.stringify it (i.e. it doesn't contain BigInts) - const contractArtifactJson = JSON.stringify(this.contractArtifact); - const buf = Buffer.concat([ - this.instance.address.toBuffer(), - new SerializableContractInstance(this.instance).toBuffer(), - prefixBufferWithLength(Buffer.from(contractArtifactJson, 'utf-8')), - ]); - - return buf; - } - - static fromBuffer(buf: Uint8Array | BufferReader) { - const reader = BufferReader.asReader(buf); - const address = AztecAddress.fromBuffer(reader); - const instance = SerializableContractInstance.fromBuffer(reader).withAddress(address); - const contractArtifact = JSON.parse(reader.readString()); - return new ContractDao(contractArtifact, instance); - } -} diff --git a/yarn-project/circuit-types/src/contract_database.ts b/yarn-project/circuit-types/src/contract_database.ts deleted file mode 100644 index f9b8581febb..00000000000 --- a/yarn-project/circuit-types/src/contract_database.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { AztecAddress } from '@aztec/foundation/aztec-address'; - -import { ContractDao } from './contract_dao.js'; - -/** - * Represents a ContractDatabase interface for managing Aztec.nr contracts. - * Provides methods for adding and retrieving ContractDao objects by their associated addresses. - */ -export interface ContractDatabase { - /** - * Adds a new ContractDao instance to the contract database. - * The function stores the contract in an array and returns a resolved promise indicating successful addition. - * - * @param contract - The ContractDao instance to be added. - * @returns A Promise that resolves when the contract is successfully added. - */ - addContract(contract: ContractDao): Promise; - - /** - * Retrieve a ContractDao instance with the specified AztecAddress. - * Returns the first match found or undefined if no contract with the given address is found. - * - * @param address - The AztecAddress to search for in the stored contracts. - * @returns A Promise resolving to the ContractDao instance matching the given address or undefined. - */ - getContract(address: AztecAddress): Promise; - - /** - * Retrieve all ContractDao instances stored in the database. - * @returns A Promise resolving to an array of all stored ContractDao instances. - */ - getContracts(): Promise; -} diff --git a/yarn-project/circuit-types/src/index.ts b/yarn-project/circuit-types/src/index.ts index d627698950e..e1b11878873 100644 --- a/yarn-project/circuit-types/src/index.ts +++ b/yarn-project/circuit-types/src/index.ts @@ -1,5 +1,3 @@ -export * from './contract_dao.js'; -export * from './contract_database.js'; export * from './contract_data.js'; export * from './function_call.js'; export * from './keys/index.js'; diff --git a/yarn-project/foundation/src/abi/function_selector.ts b/yarn-project/foundation/src/abi/function_selector.ts index fc0eaae752b..9ffcc958883 100644 --- a/yarn-project/foundation/src/abi/function_selector.ts +++ b/yarn-project/foundation/src/abi/function_selector.ts @@ -21,13 +21,20 @@ export class FunctionSelector extends Selector { * Checks if this function selector is equal to another. * @returns True if the function selectors are equal. */ + equals(fn: { name: string; parameters: ABIParameter[] }): boolean; equals(otherName: string, otherParams: ABIParameter[]): boolean; equals(other: FunctionSelector): boolean; - equals(other: FunctionSelector | string, otherParams?: ABIParameter[]): boolean { + equals( + other: FunctionSelector | string | { name: string; parameters: ABIParameter[] }, + otherParams?: ABIParameter[], + ): boolean { if (typeof other === 'string') { return this.equals(FunctionSelector.fromNameAndParameters(other, otherParams!)); + } else if (typeof other === 'object' && 'name' in other) { + return this.equals(FunctionSelector.fromNameAndParameters(other.name, other.parameters)); + } else { + return this.value === other.value; } - return this.value === other.value; } /** diff --git a/yarn-project/pxe/src/contract_data_oracle/index.ts b/yarn-project/pxe/src/contract_data_oracle/index.ts index 0a2f6519524..ad51ed876c9 100644 --- a/yarn-project/pxe/src/contract_data_oracle/index.ts +++ b/yarn-project/pxe/src/contract_data_oracle/index.ts @@ -1,12 +1,11 @@ -import { ContractDatabase } from '@aztec/circuit-types'; +import { AztecAddress, MembershipWitness, VK_TREE_HEIGHT } from '@aztec/circuits.js'; import { - AztecAddress, - ContractFunctionDao, - MembershipWitness, - VK_TREE_HEIGHT, - getContractClassFromArtifact, -} from '@aztec/circuits.js'; -import { FunctionDebugMetadata, FunctionSelector } from '@aztec/foundation/abi'; + ContractArtifact, + FunctionArtifact, + FunctionDebugMetadata, + FunctionSelector, + getFunctionDebugMetadata, +} from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; import { ContractClassNotFoundError, ContractNotFoundError } from '@aztec/simulator'; import { ContractClass, ContractInstance } from '@aztec/types/contracts'; @@ -23,27 +22,34 @@ import { PrivateFunctionsTree } from './private_functions_tree.js'; * the required information and facilitate cryptographic proof generation. */ export class ContractDataOracle { - private trees: PrivateFunctionsTree[] = []; + /** Map from contract class id to private function tree. */ + private contractClasses: Map = new Map(); + /** Map from address to contract instance. */ + private contractInstances: Map = new Map(); - constructor(private db: ContractDatabase & ContractArtifactDatabase & ContractInstanceDatabase) {} + constructor(private db: ContractArtifactDatabase & ContractInstanceDatabase) {} /** Returns a contract instance for a given address. Throws if not found. */ public async getContractInstance(contractAddress: AztecAddress): Promise { - const instance = await this.db.getContractInstance(contractAddress); - if (!instance) { - throw new ContractNotFoundError(contractAddress.toString()); + if (!this.contractInstances.has(contractAddress.toString())) { + const instance = await this.db.getContractInstance(contractAddress); + if (!instance) { + throw new ContractNotFoundError(contractAddress.toString()); + } + this.contractInstances.set(contractAddress.toString(), instance); } - return instance; + return this.contractInstances.get(contractAddress.toString())!; } - /** Returns a contract class for a given id. Throws if not found. */ + /** Returns a contract class for a given class id. Throws if not found. */ public async getContractClass(contractClassId: Fr): Promise { - const contractArtifact = await this.db.getContractArtifact(contractClassId); - if (!contractArtifact) { - throw new ContractClassNotFoundError(contractClassId.toString()); - } - // TODO(@spalladino): Cache this computation using the trees. - return getContractClassFromArtifact(contractArtifact); + const tree = await this.getTreeForClassId(contractClassId); + return tree.getContractClass(); + } + + public async getContractArtifact(contractClassId: Fr): Promise { + const tree = await this.getTreeForClassId(contractClassId); + return tree.getArtifact(); } /** @@ -56,8 +62,8 @@ export class ContractDataOracle { * @returns A Promise that resolves to the portal contract address. */ public async getPortalContractAddress(contractAddress: AztecAddress) { - const tree = await this.getTree(contractAddress); - return tree.contract.instance.portalContractAddress; + const instance = await this.getContractInstance(contractAddress); + return instance.portalContractAddress; } /** @@ -70,7 +76,7 @@ export class ContractDataOracle { * @returns The corresponding function's artifact as an object. */ public async getFunctionArtifact(contractAddress: AztecAddress, selector: FunctionSelector) { - const tree = await this.getTree(contractAddress); + const tree = await this.getTreeForAddress(contractAddress); return tree.getFunctionArtifact(selector); } @@ -86,9 +92,9 @@ export class ContractDataOracle { public async getFunctionArtifactByName( contractAddress: AztecAddress, functionName: string, - ): Promise { - const tree = await this.getTree(contractAddress); - return tree.contract.getFunctionArtifactByName(functionName); + ): Promise { + const tree = await this.getTreeForAddress(contractAddress); + return tree.getArtifact().functions.find(f => f.name === functionName); } /** @@ -105,14 +111,9 @@ export class ContractDataOracle { contractAddress: AztecAddress, selector: FunctionSelector, ): Promise { - const tree = await this.getTree(contractAddress); - const functionArtifact = tree.contract.getFunctionArtifact(selector); - - if (!functionArtifact) { - return undefined; - } - - return tree.contract.getFunctionDebugMetadataByName(functionArtifact.name); + const tree = await this.getTreeForAddress(contractAddress); + const artifact = tree.getFunctionArtifact(selector); + return getFunctionDebugMetadata(tree.getArtifact(), artifact); } /** @@ -126,7 +127,7 @@ export class ContractDataOracle { * @throws Error if the contract address is unknown or not found. */ public async getBytecode(contractAddress: AztecAddress, selector: FunctionSelector) { - const tree = await this.getTree(contractAddress); + const tree = await this.getTreeForAddress(contractAddress); return tree.getBytecode(selector); } @@ -140,7 +141,7 @@ export class ContractDataOracle { * @returns A promise that resolves with the MembershipWitness instance for the specified contract's function. */ public async getFunctionMembershipWitness(contractAddress: AztecAddress, selector: FunctionSelector) { - const tree = await this.getTree(contractAddress); + const tree = await this.getTreeForAddress(contractAddress); return tree.getFunctionMembershipWitness(selector); } @@ -158,6 +159,28 @@ export class ContractDataOracle { return await Promise.resolve(MembershipWitness.random(VK_TREE_HEIGHT)); } + /** + * Retrieve or create a ContractTree instance based on the provided class id. + * If an existing tree with the same class id is found in the cache, it will be returned. + * Otherwise, a new ContractTree instance will be created using the contract data from the database + * and added to the cache before returning. + * + * @param classId - The class id of the contract for which the ContractTree is required. + * @returns A ContractTree instance associated with the specified contract address. + * @throws An Error if the contract is not found in the ContractDatabase. + */ + private async getTreeForClassId(classId: Fr): Promise { + if (!this.contractClasses.has(classId.toString())) { + const artifact = await this.db.getContractArtifact(classId); + if (!artifact) { + throw new ContractClassNotFoundError(classId.toString()); + } + const tree = new PrivateFunctionsTree(artifact); + this.contractClasses.set(classId.toString(), tree); + } + return this.contractClasses.get(classId.toString())!; + } + /** * Retrieve or create a ContractTree instance based on the provided AztecAddress. * If an existing tree with the same contract address is found in the cache, it will be returned. @@ -168,18 +191,8 @@ export class ContractDataOracle { * @returns A ContractTree instance associated with the specified contract address. * @throws An Error if the contract is not found in the ContractDatabase. */ - private async getTree(contractAddress: AztecAddress): Promise { - // TODO(@spalladino): ContractTree should refer to a class, not an instance! - let tree = this.trees.find(t => t.contract.instance.address.equals(contractAddress)); - if (!tree) { - const contract = await this.db.getContract(contractAddress); - if (!contract) { - throw new ContractNotFoundError(contractAddress.toString()); - } - - tree = new PrivateFunctionsTree(contract); - this.trees.push(tree); - } - return tree; + private async getTreeForAddress(contractAddress: AztecAddress): Promise { + const instance = await this.getContractInstance(contractAddress); + return this.getTreeForClassId(instance.contractClassId); } } diff --git a/yarn-project/pxe/src/contract_data_oracle/private_functions_tree.ts b/yarn-project/pxe/src/contract_data_oracle/private_functions_tree.ts index 5ae3ea6b0d1..6ea2e061723 100644 --- a/yarn-project/pxe/src/contract_data_oracle/private_functions_tree.ts +++ b/yarn-project/pxe/src/contract_data_oracle/private_functions_tree.ts @@ -1,4 +1,3 @@ -import { ContractDao } from '@aztec/circuit-types'; import { FUNCTION_TREE_HEIGHT, MembershipWitness, @@ -7,7 +6,7 @@ import { getContractClassFromArtifact, } from '@aztec/circuits.js'; import { MerkleTree } from '@aztec/circuits.js/merkle'; -import { FunctionSelector } from '@aztec/foundation/abi'; +import { ContractArtifact, FunctionSelector } from '@aztec/foundation/abi'; import { Fr } from '@aztec/foundation/fields'; import { assertLength } from '@aztec/foundation/serialize'; import { ContractClassWithId } from '@aztec/types/contracts'; @@ -20,15 +19,11 @@ import { ContractClassWithId } from '@aztec/types/contracts'; */ export class PrivateFunctionsTree { private tree?: MerkleTree; - private contractClass?: ContractClassWithId; + private contractClass: ContractClassWithId; - constructor( - /** - * The contract data object containing the artifact and contract address. - * TODO(@spalladino) Replace with contract class sourced from db. - */ - public readonly contract: ContractDao, - ) {} + constructor(private readonly artifact: ContractArtifact) { + this.contractClass = getContractClassFromArtifact(artifact); + } /** * Retrieve the artifact of a given function. @@ -39,12 +34,10 @@ export class PrivateFunctionsTree { * @returns The artifact object containing relevant information about the targeted function. */ public getFunctionArtifact(selector: FunctionSelector) { - const artifact = this.contract.functions.find(f => f.selector.equals(selector)); + const artifact = this.artifact.functions.find(f => selector.equals(f.name, f.parameters)); if (!artifact) { throw new Error( - `Unknown function. Selector ${selector.toString()} not found in the artifact of contract ${this.contract.instance.address.toString()}. Expected one of: ${this.contract.functions - .map(f => `${f.name} (${f.selector.toString()})`) - .join(', ')}`, + `Unknown function. Selector ${selector.toString()} not found in the artifact with class ${this.getContractClassId().toString()}.`, ); } return artifact; @@ -75,12 +68,14 @@ export class PrivateFunctionsTree { /** Returns the contract class object. */ public getContractClass() { - if (!this.contractClass) { - this.contractClass = getContractClassFromArtifact(this.contract); - } return this.contractClass; } + /** Returns the contract artifact. */ + public getArtifact() { + return this.artifact; + } + /** * Returns the contract class identifier for the given artifact. */ diff --git a/yarn-project/pxe/src/contract_database/index.ts b/yarn-project/pxe/src/contract_database/index.ts deleted file mode 100644 index b33e27be513..00000000000 --- a/yarn-project/pxe/src/contract_database/index.ts +++ /dev/null @@ -1 +0,0 @@ -export * from './memory_contract_database.js'; diff --git a/yarn-project/pxe/src/contract_database/memory_contract_database.ts b/yarn-project/pxe/src/contract_database/memory_contract_database.ts deleted file mode 100644 index 567256def0f..00000000000 --- a/yarn-project/pxe/src/contract_database/memory_contract_database.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { ContractDao, ContractDatabase } from '@aztec/circuit-types'; -import { FunctionSelector } from '@aztec/circuits.js'; -import { AztecAddress } from '@aztec/foundation/aztec-address'; -import { DebugLogger } from '@aztec/foundation/log'; - -/** - * The MemoryContractDatabase class serves as an in-memory implementation of the ContractDatabase interface. - * It allows for storing and retrieving contract data, such as ContractDao objects and associated function bytecodes, - * within a contracts array. This class is particularly useful for testing and development purposes where a - * persistent storage may not be required. - */ -export class MemoryContractDatabase implements ContractDatabase { - private contracts: ContractDao[] = []; - - constructor(protected log: DebugLogger) {} - - /** - * Adds a new ContractDao instance to the memory-based contract database. - * The function stores the contract in an array and returns a resolved promise indicating successful addition. - * - * @param contract - The ContractDao instance to be added to the memory database. - * @returns A Promise that resolves when the contract is successfully added. - */ - public addContract(contract: ContractDao) { - this.log(`Adding contract ${contract.instance.address.toString()}`); - this.contracts.push(contract); - return Promise.resolve(); - } - - /** - * Retrieve a ContractDao instance with the specified AztecAddress from the in-memory contracts list. - * Returns the first match found or undefined if no contract with the given address is found. - * - * @param address - The AztecAddress to search for in the stored contracts. - * @returns A Promise resolving to the ContractDao instance matching the given address or undefined. - */ - public getContract(address: AztecAddress): Promise { - return Promise.resolve(this.contracts.find(c => c.instance.address.equals(address))); - } - - public getContracts(): Promise { - return Promise.resolve(this.contracts); - } - - /** - * Retrieve the bytecode associated with a given contract address and function selector. - * This function searches through the stored contracts to find a matching contract and function, - * then returns the corresponding bytecode. If no match is found, it returns undefined. - * - * @param contractAddress - The AztecAddress representing the contract address to look for. - * @param selector - The function selector. - * @returns A Promise that resolves to the bytecode of the matching function or undefined if not found. - */ - public async getCode(contractAddress: AztecAddress, selector: FunctionSelector) { - const contract = await this.getContract(contractAddress); - return contract?.functions.find(f => f.selector.equals(selector))?.bytecode; - } -} diff --git a/yarn-project/pxe/src/database/contracts/contract_instance_db.ts b/yarn-project/pxe/src/database/contracts/contract_instance_db.ts index 30dd44bed9e..0fbd0696384 100644 --- a/yarn-project/pxe/src/database/contracts/contract_instance_db.ts +++ b/yarn-project/pxe/src/database/contracts/contract_instance_db.ts @@ -15,4 +15,7 @@ export interface ContractInstanceDatabase { * @param address - Address of the contract. */ getContractInstance(address: AztecAddress): Promise; + + /** Returns the addresses all contract instances registered in the DB. */ + getContractsAddresses(): Promise; } diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index c63b913ea77..8fabdf14872 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -1,4 +1,4 @@ -import { ContractDao, MerkleTreeId, NoteFilter, NoteStatus, PublicKey } from '@aztec/circuit-types'; +import { MerkleTreeId, NoteFilter, NoteStatus, PublicKey } from '@aztec/circuit-types'; import { AztecAddress, CompleteAddress, Header } from '@aztec/circuits.js'; import { ContractArtifact } from '@aztec/foundation/abi'; import { toBufferBE } from '@aztec/foundation/bigint-buffer'; @@ -20,7 +20,6 @@ export class KVPxeDatabase implements PxeDatabase { #addressIndex: AztecMap; #authWitnesses: AztecMap; #capsules: AztecArray; - #contracts: AztecMap; #notes: AztecMap; #nullifiedNotes: AztecMap; #nullifierToNoteId: AztecMap; @@ -47,7 +46,6 @@ export class KVPxeDatabase implements PxeDatabase { this.#authWitnesses = db.openMap('auth_witnesses'); this.#capsules = db.openArray('capsules'); - this.#contracts = db.openMap('contracts'); this.#contractArtifacts = db.openMap('contract_artifacts'); this.#contractInstances = db.openMap('contracts_instances'); @@ -73,11 +71,22 @@ export class KVPxeDatabase implements PxeDatabase { this.#deferredNotesByContract = db.openMultiMap('deferred_notes_by_contract'); } + public async getContract( + address: AztecAddress, + ): Promise<(ContractInstanceWithAddress & ContractArtifact) | undefined> { + const instance = await this.getContractInstance(address); + const artifact = instance && (await this.getContractArtifact(instance?.contractClassId)); + if (!instance || !artifact) { + return undefined; + } + return { ...instance, ...artifact }; + } + public async addContractArtifact(id: Fr, contract: ContractArtifact): Promise { await this.#contractArtifacts.set(id.toString(), contractArtifactToBuffer(contract)); } - getContractArtifact(id: Fr): Promise { + public getContractArtifact(id: Fr): Promise { const contract = this.#contractArtifacts.get(id.toString()); // TODO(@spalladino): AztecMap lies and returns Uint8Arrays instead of Buffers, hence the extra Buffer.from. return Promise.resolve(contract && contractArtifactFromBuffer(Buffer.from(contract))); @@ -95,6 +104,10 @@ export class KVPxeDatabase implements PxeDatabase { return Promise.resolve(contract && SerializableContractInstance.fromBuffer(contract).withAddress(address)); } + getContractsAddresses(): Promise { + return Promise.resolve(Array.from(this.#contractInstances.keys()).map(AztecAddress.fromString)); + } + async addAuthWitness(messageHash: Fr, witness: Fr[]): Promise { await this.#authWitnesses.set( messageHash.toString(), @@ -393,17 +406,4 @@ export class KVPxeDatabase implements PxeDatabase { return notesSize + treeRootsSize + authWitsSize + addressesSize; } - - async addContract(contract: ContractDao): Promise { - await this.#contracts.set(contract.instance.address.toString(), contract.toBuffer()); - } - - getContract(address: AztecAddress): Promise { - const contract = this.#contracts.get(address.toString()); - return Promise.resolve(contract ? ContractDao.fromBuffer(contract) : undefined); - } - - getContracts(): Promise { - return Promise.resolve(Array.from(this.#contracts.values()).map(c => ContractDao.fromBuffer(c))); - } } diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index f97847dfe97..a755f710331 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -1,7 +1,9 @@ -import { ContractDatabase, NoteFilter } from '@aztec/circuit-types'; +import { NoteFilter } from '@aztec/circuit-types'; import { CompleteAddress, Header, PublicKey } from '@aztec/circuits.js'; +import { ContractArtifact } from '@aztec/foundation/abi'; import { AztecAddress } from '@aztec/foundation/aztec-address'; import { Fr } from '@aztec/foundation/fields'; +import { ContractInstanceWithAddress } from '@aztec/types/contracts'; import { ContractArtifactDatabase } from './contracts/contract_artifact_db.js'; import { ContractInstanceDatabase } from './contracts/contract_instance_db.js'; @@ -12,7 +14,9 @@ import { NoteDao } from './note_dao.js'; * A database interface that provides methods for retrieving, adding, and removing transactional data related to Aztec * addresses, storage slots, and nullifiers. */ -export interface PxeDatabase extends ContractDatabase, ContractArtifactDatabase, ContractInstanceDatabase { +export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceDatabase { + getContract(address: AztecAddress): Promise<(ContractInstanceWithAddress & ContractArtifact) | undefined>; + /** * Add a auth witness to the database. * @param messageHash - The message hash. diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index f9bdb5c9bf2..9f4b68afa11 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -1,7 +1,6 @@ import { AuthWitness, AztecNode, - ContractDao, ContractData, DeployedContract, ExtendedNote, @@ -39,7 +38,7 @@ import { getContractClassFromArtifact, } from '@aztec/circuits.js'; import { computeCommitmentNonce, siloNullifier } from '@aztec/circuits.js/hash'; -import { DecodedReturn, encodeArguments } from '@aztec/foundation/abi'; +import { DecodedReturn, FunctionSelector, encodeArguments } from '@aztec/foundation/abi'; import { arrayNonEmptyLength, padArrayEnd } from '@aztec/foundation/collection'; import { Fr } from '@aztec/foundation/fields'; import { SerialQueue } from '@aztec/foundation/fifo'; @@ -218,31 +217,21 @@ export class PXEService implements PXE { } public async addContracts(contracts: DeployedContract[]) { - const contractDaos = contracts.map(c => new ContractDao(c.artifact, c.instance)); - await Promise.all(contractDaos.map(c => this.db.addContract(c))); - await this.addArtifactsAndInstancesFromDeployedContracts(contracts); - for (const contract of contractDaos) { - const instance = contract.instance; - const contractAztecAddress = instance.address; - const hasPortal = instance.portalContractAddress && !instance.portalContractAddress.isZero(); - const portalInfo = hasPortal ? ` with portal ${instance.portalContractAddress.toChecksumString()}` : ''; - this.log.info(`Added contract ${contract.name} at ${contractAztecAddress}${portalInfo}`); - await this.synchronizer.reprocessDeferredNotesForContract(contractAztecAddress); - } - } - - private async addArtifactsAndInstancesFromDeployedContracts(contracts: DeployedContract[]) { for (const contract of contracts) { - const artifact = contract.artifact; + const { instance, artifact } = contract; const artifactHash = computeArtifactHash(artifact); const contractClassId = computeContractClassId(getContractClassFromArtifact({ ...artifact, artifactHash })); await this.db.addContractArtifact(contractClassId, artifact); - await this.db.addContractInstance(contract.instance); + await this.db.addContractInstance(instance); + const hasPortal = instance.portalContractAddress && !instance.portalContractAddress.isZero(); + const portalInfo = hasPortal ? ` with portal ${instance.portalContractAddress.toChecksumString()}` : ''; + this.log.info(`Added contract ${artifact.name} at ${instance.address.toString()}${portalInfo}`); + await this.synchronizer.reprocessDeferredNotesForContract(instance.address); } } - public async getContracts(): Promise { - return (await this.db.getContracts()).map(c => c.instance.address); + public getContracts(): Promise { + return this.db.getContractsAddresses(); } public async getPublicStorageAt(contract: AztecAddress, slot: Fr) { @@ -649,9 +638,13 @@ export class PXEService implements PXE { if (contract) { err.enrichWithContractName(parsedContractAddress, contract.name); selectors.forEach(selector => { - const functionArtifact = contract.functions.find(f => f.selector.toString() === selector); + const functionArtifact = contract.functions.find(f => FunctionSelector.fromString(selector).equals(f)); if (functionArtifact) { - err.enrichWithFunctionName(parsedContractAddress, functionArtifact.selector, functionArtifact.name); + err.enrichWithFunctionName( + parsedContractAddress, + FunctionSelector.fromNameAndParameters(functionArtifact), + functionArtifact.name, + ); } }); } diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index b105f4a1e8a..63f84b0e970 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -16,7 +16,7 @@ import { Header, L1_TO_L2_MSG_TREE_HEIGHT, } from '@aztec/circuits.js'; -import { FunctionArtifactWithDebugMetadata } from '@aztec/foundation/abi'; +import { FunctionArtifactWithDebugMetadata, getFunctionArtifactWithDebugMetadata } from '@aztec/foundation/abi'; import { createDebugLogger } from '@aztec/foundation/log'; import { DBOracle, KeyPair, MessageLoadOracleInputs } from '@aztec/simulator'; import { ContractInstance } from '@aztec/types/contracts'; @@ -111,16 +111,9 @@ export class SimulatorOracle implements DBOracle { contractAddress: AztecAddress, functionName: string, ): Promise { - const artifact = await this.contractDataOracle.getFunctionArtifactByName(contractAddress, functionName); - if (!artifact) { - return; - } - - const debug = await this.contractDataOracle.getFunctionDebugMetadata(contractAddress, artifact.selector); - return { - ...artifact, - debug, - }; + const instance = await this.contractDataOracle.getContractInstance(contractAddress); + const artifact = await this.contractDataOracle.getContractArtifact(instance.contractClassId); + return artifact && getFunctionArtifactWithDebugMetadata(artifact, functionName); } async getPortalContractAddress(contractAddress: AztecAddress): Promise {