diff --git a/yarn-project/aztec.js/src/contract/contract.test.ts b/yarn-project/aztec.js/src/contract/contract.test.ts index 4e856779ad4a..335844c96337 100644 --- a/yarn-project/aztec.js/src/contract/contract.test.ts +++ b/yarn-project/aztec.js/src/contract/contract.test.ts @@ -147,7 +147,11 @@ describe('Contract Class', () => { wallet = mock(); wallet.simulateTx.mockResolvedValue(mockTxSimulationResult); wallet.createTxExecutionRequest.mockResolvedValue(mockTxRequest); - wallet.getContractInstance.mockResolvedValue(contractInstance); + wallet.getContractMetadata.mockResolvedValue({ + contractInstance, + isContractInitialized: true, + isContractPubliclyDeployed: true, + }); wallet.sendTx.mockResolvedValue(mockTxHash); wallet.simulateUnconstrained.mockResolvedValue(mockUnconstrainedResultValue as any as AbiDecoded); wallet.getTxReceipt.mockResolvedValue(mockTxReceipt); diff --git a/yarn-project/aztec.js/src/contract/contract.ts b/yarn-project/aztec.js/src/contract/contract.ts index 708b220386ea..6472a9da8800 100644 --- a/yarn-project/aztec.js/src/contract/contract.ts +++ b/yarn-project/aztec.js/src/contract/contract.ts @@ -22,7 +22,7 @@ export class Contract extends ContractBase { * @returns A promise that resolves to a new Contract instance. */ public static async at(address: AztecAddress, artifact: ContractArtifact, wallet: Wallet): Promise { - const instance = await wallet.getContractInstance(address); + const instance = (await wallet.getContractMetadata(address)).contractInstance; if (instance === undefined) { throw new Error(`Contract instance at ${address.toString()} has not been registered in the wallet's PXE`); } diff --git a/yarn-project/aztec.js/src/contract/deploy_method.ts b/yarn-project/aztec.js/src/contract/deploy_method.ts index 869981308a77..210808390b3b 100644 --- a/yarn-project/aztec.js/src/contract/deploy_method.ts +++ b/yarn-project/aztec.js/src/contract/deploy_method.ts @@ -153,7 +153,7 @@ export class DeployMethod extends Bas // Register the contract class if it hasn't been published already. if (!options.skipClassRegistration) { - if (await this.wallet.isContractClassPubliclyRegistered(contractClass.id)) { + if ((await this.wallet.getContractClassMetadata(contractClass.id)).isContractClassPubliclyRegistered) { this.log.debug( `Skipping registration of already registered contract class ${contractClass.id.toString()} for ${instance.address.toString()}`, ); diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index aaf2bea19546..a97c0445304e 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -1,5 +1,7 @@ import { type AuthWitness, + ContractClassMetadata, + ContractMetadata, type EventMetadataDefinition, type ExtendedNote, type GetUnencryptedLogsResponse, @@ -65,15 +67,6 @@ export abstract class BaseWallet implements Wallet { getAddress() { return this.getCompleteAddress().address; } - getContractInstance(address: AztecAddress): Promise { - return this.pxe.getContractInstance(address); - } - getContractClass(id: Fr): Promise { - return this.pxe.getContractClass(id); - } - getContractArtifact(id: Fr): Promise { - return this.pxe.getContractArtifact(id); - } addCapsule(capsule: Fr[]): Promise { return this.pxe.addCapsule(capsule); } @@ -83,9 +76,6 @@ export abstract class BaseWallet implements Wallet { getRegisteredAccounts(): Promise { return this.pxe.getRegisteredAccounts(); } - getRegisteredAccount(address: AztecAddress): Promise { - return this.pxe.getRegisteredAccount(address); - } registerContact(address: AztecAddress): Promise { return this.pxe.registerContact(address); } @@ -131,9 +121,6 @@ export abstract class BaseWallet implements Wallet { getIncomingNotes(filter: IncomingNotesFilter): Promise { return this.pxe.getIncomingNotes(filter); } - getOutgoingNotes(filter: OutgoingNotesFilter): Promise { - return this.pxe.getOutgoingNotes(filter); - } getPublicStorageAt(contract: AztecAddress, storageSlot: Fr): Promise { return this.pxe.getPublicStorageAt(contract, storageSlot); } @@ -184,18 +171,15 @@ export abstract class BaseWallet implements Wallet { getAuthWitness(messageHash: Fr) { return this.pxe.getAuthWitness(messageHash); } - isContractClassPubliclyRegistered(id: Fr): Promise { - return this.pxe.isContractClassPubliclyRegistered(id); - } - isContractPubliclyDeployed(address: AztecAddress): Promise { - return this.pxe.isContractPubliclyDeployed(address); - } - isContractInitialized(address: AztecAddress): Promise { - return this.pxe.isContractInitialized(address); - } getPXEInfo(): Promise { return this.pxe.getPXEInfo(); } + getContractClassMetadata(id: Fr, includeArtifact: boolean = false): Promise { + return this.pxe.getContractClassMetadata(id, includeArtifact); + } + getContractMetadata(address: AztecAddress): Promise { + return this.pxe.getContractMetadata(address); + } getEncryptedEvents( event: EventMetadataDefinition, from: number, diff --git a/yarn-project/aztec.js/src/wallet/index.ts b/yarn-project/aztec.js/src/wallet/index.ts index 08e8cb27c416..6479e8c50bb0 100644 --- a/yarn-project/aztec.js/src/wallet/index.ts +++ b/yarn-project/aztec.js/src/wallet/index.ts @@ -21,7 +21,9 @@ export async function getWallet( address: AztecAddress, accountContract: AccountContract, ): Promise { - const completeAddress = await pxe.getRegisteredAccount(address); + const completeAddress = (await pxe.getRegisteredAccounts()).find(completeAddress => + completeAddress.address.equals(address), + ); if (!completeAddress) { throw new Error(`Account ${address} not found`); } diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index d41ddf174ff1..e8562a59ca55 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -63,7 +63,7 @@ export class BotFactory { const salt = Fr.ONE; const signingKey = deriveSigningKey(this.config.senderPrivateKey); const account = getSchnorrAccount(this.pxe, this.config.senderPrivateKey, signingKey, salt); - const isInit = await this.pxe.isContractInitialized(account.getAddress()); + const isInit = (await this.pxe.getContractMetadata(account.getAddress())).isContractInitialized; if (isInit) { this.log.info(`Account at ${account.getAddress().toString()} already initialized`); const wallet = await account.register(); @@ -122,7 +122,7 @@ export class BotFactory { } const address = deploy.getInstance(deployOpts).address; - if (await this.pxe.isContractPubliclyDeployed(address)) { + if ((await this.pxe.getContractMetadata(address)).isContractPubliclyDeployed) { this.log.info(`Token at ${address.toString()} already deployed`); return deploy.register(); } else { diff --git a/yarn-project/circuit-types/src/interfaces/pxe.test.ts b/yarn-project/circuit-types/src/interfaces/pxe.test.ts index 294ba5199885..93fb1f323324 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.test.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.test.ts @@ -42,7 +42,14 @@ import { SiblingPath } from '../sibling_path/sibling_path.js'; import { Tx, TxHash, TxProvingResult, TxReceipt, TxSimulationResult } from '../tx/index.js'; import { TxEffect } from '../tx_effect.js'; import { TxExecutionRequest } from '../tx_execution_request.js'; -import { type EventMetadataDefinition, type PXE, type PXEInfo, PXESchema } from './pxe.js'; +import { + ContractClassMetadata, + ContractMetadata, + type EventMetadataDefinition, + type PXE, + type PXEInfo, + PXESchema, +} from './pxe.js'; import { type SyncStatus } from './sync-status.js'; jest.setTimeout(12_000); @@ -110,11 +117,6 @@ describe('PXESchema', () => { expect(result).toEqual([expect.any(CompleteAddress)]); }); - it('getRegisteredAccount', async () => { - const result = await context.client.getRegisteredAccount(address); - expect(result).toBeInstanceOf(CompleteAddress); - }); - it('registerContact', async () => { const result = await context.client.registerContact(address); expect(result).toEqual(address); @@ -201,11 +203,6 @@ describe('PXESchema', () => { expect(result).toEqual([expect.any(BigInt), expect.any(SiblingPath)]); }); - it('getOutgoingNotes', async () => { - const result = await context.client.getOutgoingNotes({ contractAddress: address }); - expect(result).toEqual([expect.any(UniqueNote)]); - }); - it('addNote', async () => { await context.client.addNote(ExtendedNote.random(), address); }); @@ -269,35 +266,24 @@ describe('PXESchema', () => { expect(result).toEqual(await handler.getSyncStatus()); }); - it('getContractInstance', async () => { - const result = await context.client.getContractInstance(address); - expect(result).toEqual(instance); + it('getContractMetadata', async () => { + const { contractInstance, isContractInitialized, isContractPubliclyDeployed } = + await context.client.getContractMetadata(address); + expect(contractInstance).toEqual(instance); + expect(isContractInitialized).toEqual(true); + expect(isContractPubliclyDeployed).toEqual(true); }); - it('getContractClass', async () => { - const result = await context.client.getContractClass(Fr.random()); + it('getContractClassMetadata', async () => { + const { + contractClass, + isContractClassPubliclyRegistered, + artifact: contractArtifact, + } = await context.client.getContractClassMetadata(Fr.random(), true); const expected = omit(getContractClassFromArtifact(artifact), 'privateFunctionsRoot', 'publicBytecodeCommitment'); - expect(result).toEqual(expected); - }); - - it('getContractArtifact', async () => { - const result = await context.client.getContractArtifact(Fr.random()); - deepStrictEqual(result, artifact); - }); - - it('isContractClassPubliclyRegistered', async () => { - const result = await context.client.isContractClassPubliclyRegistered(Fr.random()); - expect(result).toBe(true); - }); - - it('isContractPubliclyDeployed', async () => { - const result = await context.client.isContractPubliclyDeployed(address); - expect(result).toBe(true); - }); - - it('isContractInitialized', async () => { - const result = await context.client.isContractInitialized(address); - expect(result).toBe(true); + expect(contractClass).toEqual(expected); + expect(isContractClassPubliclyRegistered).toEqual(true); + deepStrictEqual(contractArtifact, artifact); }); it('getEncryptedEvents', async () => { @@ -433,10 +419,6 @@ class MockPXE implements PXE { expect(secret).toBeInstanceOf(Fr); return Promise.resolve([1n, SiblingPath.random(L1_TO_L2_MSG_TREE_HEIGHT)]); } - getOutgoingNotes(filter: OutgoingNotesFilter): Promise { - expect(filter.contractAddress).toEqual(this.address); - return Promise.resolve([UniqueNote.random()]); - } addNote(note: ExtendedNote, scope?: AztecAddress | undefined): Promise { expect(note).toBeInstanceOf(ExtendedNote); expect(scope).toEqual(this.address); @@ -510,30 +492,22 @@ class MockPXE implements PXE { blocks: 1, }); } - getContractInstance(address: AztecAddress): Promise { - expect(address).toEqual(this.address); - return Promise.resolve(this.instance); - } - getContractClass(id: Fr): Promise { + getContractClassMetadata(id: Fr, includeArtifact: boolean = false): Promise { expect(id).toBeInstanceOf(Fr); const contractClass = getContractClassFromArtifact(this.artifact); - return Promise.resolve(contractClass); - } - getContractArtifact(id: Fr): Promise { - expect(id).toBeInstanceOf(Fr); - return Promise.resolve(this.artifact); - } - isContractClassPubliclyRegistered(id: Fr): Promise { - expect(id).toBeInstanceOf(Fr); - return Promise.resolve(true); - } - isContractPubliclyDeployed(address: AztecAddress): Promise { - expect(address).toEqual(this.address); - return Promise.resolve(true); + return Promise.resolve({ + contractClass, + isContractClassPubliclyRegistered: true, + artifact: includeArtifact ? this.artifact : undefined, + }); } - isContractInitialized(address: AztecAddress): Promise { + getContractMetadata(address: AztecAddress): Promise { expect(address).toEqual(this.address); - return Promise.resolve(true); + return Promise.resolve({ + contractInstance: this.instance, + isContractInitialized: true, + isContractPubliclyDeployed: true, + }); } getEncryptedEvents( _eventMetadata: EventMetadataDefinition, diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 0ff0f322ecfb..7e422af8b824 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -99,15 +99,6 @@ export interface PXE { */ getRegisteredAccounts(): Promise; - /** - * Retrieves the complete address of the account corresponding to the provided aztec address. - * Complete addresses include the address, the partial address, and the encryption public key. - * - * @param address - The address of account. - * @returns The complete address of the requested account if found. - */ - getRegisteredAccount(address: AztecAddress): Promise; - /** * Registers a user contact in PXE. * @@ -254,13 +245,6 @@ export interface PXE { secret: Fr, ): Promise<[bigint, SiblingPath]>; - /** - * Gets outgoing notes of accounts registered in this PXE based on the provided filter. - * @param filter - The filter to apply to the notes. - * @returns The requested notes. - */ - getOutgoingNotes(filter: OutgoingNotesFilter): Promise; - /** * Adds a note to the database. * @throws If the note hash of the note doesn't exist in the tree. @@ -368,49 +352,33 @@ export interface PXE { getSyncStatus(): Promise; /** - * Returns a Contract Instance given its address, which includes the contract class identifier, - * initialization hash, deployment salt, and public keys hash. + * Returns the contract metadata given an address. + * The metadata consists of its contract instance, which includes the contract class identifier, + * initialization hash, deployment salt, and public keys hash; whether the contract instance has been initialized; + * and whether the contract instance with the given address has been publicly deployed. + * @remark - it queries the node to check whether the contract instance has been initialized / publicly deployed through a node. + * This query is not dependent on the PXE. + * @param address - The address that the contract instance resides at. + * @returns - It returns the contract metadata * TODO(@spalladino): Should we return the public keys in plain as well here? - * @param address - Deployment address of the contract. */ - getContractInstance(address: AztecAddress): Promise; + getContractMetadata(address: AztecAddress): Promise; /** - * Returns a Contract Class given its identifier. + * Returns the contract class metadata given a contract class id. + * The metadata consists of its contract class, whether it has been publicly registered, and its artifact. + * @remark - it queries the node to check whether the contract class with the given id has been publicly registered. + * @param id - Identifier of the class. + * @param includeArtifact - Identifier of the class. + * @returns - It returns the contract class metadata, with the artifact field being optional, and will only be returned if true is passed in + * for `includeArtifact` * TODO(@spalladino): The PXE actually holds artifacts and not classes, what should we return? Also, * should the pxe query the node for contract public info, and merge it with its own definitions? - * @param id - Identifier of the class. - */ - getContractClass(id: Fr): Promise; - - /** - * Returns the contract artifact associated to a contract class. - * @param id - Identifier of the class. - */ - getContractArtifact(id: Fr): Promise; - - /** - * Queries the node to check whether the contract class with the given id has been publicly registered. * TODO(@spalladino): This method is strictly needed to decide whether to publicly register a class or not * during a public deployment. We probably want a nicer and more general API for this, but it'll have to * do for the time being. - * @param id - Identifier of the class. */ - isContractClassPubliclyRegistered(id: Fr): Promise; - - /** - * Queries the node to check whether the contract instance with the given address has been publicly deployed, - * regardless of whether this PXE knows about the contract or not. - * TODO(@spalladino): Same notes as above. - */ - isContractPubliclyDeployed(address: AztecAddress): Promise; - - /** - * Queries the node to check whether the contract instance with the given address has been initialized, - * by checking the standard initialization nullifier. - * @param address - Address of the contract to check. - */ - isContractInitialized(address: AztecAddress): Promise; + getContractClassMetadata(id: Fr, includeArtifact?: boolean): Promise; /** * Returns the enctypred events given search parameters. @@ -464,6 +432,30 @@ export interface PXEInfo { protocolContractAddresses: ProtocolContractAddresses; } +export interface ContractMetadata { + contractInstance?: ContractInstanceWithAddress | undefined; + isContractInitialized: boolean; + isContractPubliclyDeployed: boolean; +} + +export interface ContractClassMetadata { + contractClass?: ContractClassWithId | undefined; + isContractClassPubliclyRegistered: boolean; + artifact?: ContractArtifact | undefined; +} + +const ContractMetadataSchema = z.object({ + contractInstance: z.union([ContractInstanceWithAddressSchema, z.undefined()]), + isContractInitialized: z.boolean(), + isContractPubliclyDeployed: z.boolean(), +}) satisfies ZodFor; + +const ContractClassMetadataSchema = z.object({ + contractClass: z.union([ContractClassWithIdSchema, z.undefined()]), + isContractClassPubliclyRegistered: z.boolean(), + artifact: z.union([ContractArtifactSchema, z.undefined()]), +}) satisfies ZodFor; + const PXEInfoSchema = z.object({ pxeVersion: z.string(), protocolContractAddresses: ProtocolContractAddressesSchema, @@ -478,10 +470,6 @@ export const PXESchema: ApiSchemaFor = { addCapsule: z.function().args(z.array(schemas.Fr)).returns(z.void()), registerAccount: z.function().args(schemas.Fr, schemas.Fr).returns(CompleteAddress.schema), getRegisteredAccounts: z.function().returns(z.array(CompleteAddress.schema)), - getRegisteredAccount: z - .function() - .args(schemas.AztecAddress) - .returns(z.union([CompleteAddress.schema, z.undefined()])), registerContact: z.function().args(schemas.AztecAddress).returns(schemas.AztecAddress), getContacts: z.function().returns(z.array(schemas.AztecAddress)), removeContact: z.function().args(schemas.AztecAddress).returns(z.void()), @@ -515,7 +503,6 @@ export const PXESchema: ApiSchemaFor = { .function() .args(schemas.AztecAddress, schemas.Fr, schemas.Fr) .returns(z.tuple([schemas.BigInt, SiblingPath.schemaFor(L1_TO_L2_MSG_TREE_HEIGHT)])), - getOutgoingNotes: z.function().args(OutgoingNotesFilterSchema).returns(z.array(UniqueNote.schema)), addNote: z.function().args(ExtendedNote.schema, optional(schemas.AztecAddress)).returns(z.void()), addNullifiedNote: z.function().args(ExtendedNote.schema).returns(z.void()), getBlock: z @@ -542,21 +529,8 @@ export const PXESchema: ApiSchemaFor = { getPXEInfo: z.function().returns(PXEInfoSchema), isGlobalStateSynchronized: z.function().returns(z.boolean()), getSyncStatus: z.function().returns(SyncStatusSchema), - getContractInstance: z - .function() - .args(schemas.AztecAddress) - .returns(z.union([ContractInstanceWithAddressSchema, z.undefined()])), - getContractClass: z - .function() - .args(schemas.Fr) - .returns(z.union([ContractClassWithIdSchema, z.undefined()])), - getContractArtifact: z - .function() - .args(schemas.Fr) - .returns(z.union([ContractArtifactSchema, z.undefined()])), - isContractClassPubliclyRegistered: z.function().args(schemas.Fr).returns(z.boolean()), - isContractPubliclyDeployed: z.function().args(schemas.AztecAddress).returns(z.boolean()), - isContractInitialized: z.function().args(schemas.AztecAddress).returns(z.boolean()), + getContractMetadata: z.function().args(schemas.AztecAddress).returns(ContractMetadataSchema), + getContractClassMetadata: z.function().args(schemas.Fr, optional(z.boolean())).returns(ContractClassMetadataSchema), getEncryptedEvents: z .function() .args(EventMetadataDefinitionSchema, z.number(), z.number(), z.array(schemas.Point)) diff --git a/yarn-project/cli/src/cmds/pxe/get_account.ts b/yarn-project/cli/src/cmds/pxe/get_account.ts index e54f8ada5680..6722cb9e6024 100644 --- a/yarn-project/cli/src/cmds/pxe/get_account.ts +++ b/yarn-project/cli/src/cmds/pxe/get_account.ts @@ -4,7 +4,9 @@ import { type DebugLogger, type LogFn } from '@aztec/foundation/log'; export async function getAccount(aztecAddress: AztecAddress, rpcUrl: string, debugLogger: DebugLogger, log: LogFn) { const client = await createCompatibleClient(rpcUrl, debugLogger); - const account = await client.getRegisteredAccount(aztecAddress); + const account = (await client.getRegisteredAccounts()).find(completeAddress => + completeAddress.address.equals(aztecAddress), + ); if (!account) { log(`Unknown account ${aztecAddress.toString()}`); diff --git a/yarn-project/cli/src/cmds/pxe/get_contract_data.ts b/yarn-project/cli/src/cmds/pxe/get_contract_data.ts index 34972a33d840..ff2166cb88fe 100644 --- a/yarn-project/cli/src/cmds/pxe/get_contract_data.ts +++ b/yarn-project/cli/src/cmds/pxe/get_contract_data.ts @@ -10,12 +10,15 @@ export async function getContractData( log: LogFn, ) { const client = await createCompatibleClient(rpcUrl, debugLogger); - const instance = await client.getContractInstance(contractAddress); - const contractClass = includeBytecode && instance && (await client.getContractClass(instance?.contractClassId)); + const { + contractInstance: instance, + isContractInitialized: isInitialized, + isContractPubliclyDeployed: isPubliclyDeployed, + } = await client.getContractMetadata(contractAddress); + const contractClass = + includeBytecode && instance && (await client.getContractClassMetadata(instance?.contractClassId)).contractClass; const isPrivatelyDeployed = !!instance; - const isPubliclyDeployed = await client.isContractPubliclyDeployed(contractAddress); - const isInitialized = await client.isContractInitialized(contractAddress); const initStr = isInitialized ? 'initialized' : 'not initialized'; const addrStr = contractAddress.toString(); diff --git a/yarn-project/cli/src/utils/inspect.ts b/yarn-project/cli/src/utils/inspect.ts index 80c87f4c79d0..2fd829859e6d 100644 --- a/yarn-project/cli/src/utils/inspect.ts +++ b/yarn-project/cli/src/utils/inspect.ts @@ -182,17 +182,23 @@ type ArtifactMap = Record; type ContractArtifactWithClassId = ContractArtifact & { classId: Fr }; async function getKnownArtifacts(pxe: PXE): Promise { const knownContractAddresses = await pxe.getContracts(); - const knownContracts = await Promise.all(knownContractAddresses.map(contract => pxe.getContractInstance(contract))); + const knownContracts = ( + await Promise.all(knownContractAddresses.map(contractAddress => pxe.getContractMetadata(contractAddress))) + ).map(contractMetadata => contractMetadata.contractInstance); const classIds = [...new Set(knownContracts.map(contract => contract?.contractClassId))]; - const knownArtifacts = await Promise.all( - classIds.map(classId => - classId ? pxe.getContractArtifact(classId).then(a => (a ? { ...a, classId } : undefined)) : undefined, - ), + const knownArtifacts = ( + await Promise.all(classIds.map(classId => (classId ? pxe.getContractClassMetadata(classId) : undefined))) + ).map(contractClassMetadata => + contractClassMetadata + ? { ...contractClassMetadata.artifact, classId: contractClassMetadata.contractClass?.id } + : undefined, ); const map: Record = {}; for (const instance of knownContracts) { if (instance) { - const artifact = knownArtifacts.find(a => a?.classId.equals(instance.contractClassId)); + const artifact = knownArtifacts.find(a => + a?.classId?.equals(instance.contractClassId), + ) as ContractArtifactWithClassId; if (artifact) { map[instance.address.toString()] = artifact; } diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index d3dded0788d4..654fbf24da11 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -256,13 +256,8 @@ describe('e2e_2_pxes', () => { .wait(); await testContract.methods.sync_notes().simulate(); const incomingNotes = await walletA.getIncomingNotes({ txHash: receipt.txHash }); - const outgoingNotes = await walletA.getOutgoingNotes({ txHash: receipt.txHash }); expect(incomingNotes).toHaveLength(1); note = incomingNotes[0]; - - // Since owner is the same as outgoing viewer the incoming and outgoing notes should be the same - expect(outgoingNotes).toHaveLength(1); - expect(outgoingNotes[0]).toEqual(note); } // 3. Nullify the note diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 4989a66d0a9c..9dc05c71d417 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -91,7 +91,8 @@ describe('e2e_block_building', () => { expect(receipts.map(r => r.blockNumber)).toEqual(times(TX_COUNT, () => receipts[0].blockNumber)); // Assert all contracts got deployed - const isContractDeployed = async (address: AztecAddress) => !!(await pxe.getContractInstance(address)); + const isContractDeployed = async (address: AztecAddress) => + !!(await pxe.getContractMetadata(address)).contractInstance; const areDeployed = await Promise.all(receipts.map(r => isContractDeployed(r.contract.address))); expect(areDeployed).toEqual(times(TX_COUNT, () => true)); }); diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts index a1f6442a81ff..d66d8440ddec 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/legacy.test.ts @@ -42,8 +42,8 @@ describe('e2e_deploy_contract legacy', () => { const deployer = new ContractDeployer(TestContractArtifact, wallet, publicKeys); const receipt = await deployer.deploy().send({ contractAddressSalt: salt }).wait({ wallet }); expect(receipt.contract.address).toEqual(deploymentData.address); - expect(await pxe.getContractInstance(deploymentData.address)).toBeDefined(); - expect(await pxe.isContractPubliclyDeployed(deploymentData.address)).toBeDefined(); + expect((await pxe.getContractMetadata(deploymentData.address)).contractInstance).toBeDefined(); + expect((await pxe.getContractMetadata(deploymentData.address)).isContractPubliclyDeployed).toBeTrue(); }); /** @@ -113,7 +113,10 @@ describe('e2e_deploy_contract legacy', () => { expect(badTxReceipt.status).toEqual(TxStatus.APP_LOGIC_REVERTED); + const { isContractClassPubliclyRegistered } = await pxe.getContractClassMetadata( + badDeploy.getInstance().contractClassId, + ); // But the bad tx did not deploy - await expect(pxe.isContractClassPubliclyRegistered(badDeploy.getInstance().contractClassId)).resolves.toBeFalsy(); + expect(isContractClassPubliclyRegistered).toBeFalse(); }); }); diff --git a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts index 87699648c198..b5873a413aff 100644 --- a/yarn-project/end-to-end/src/e2e_fees/fees_test.ts +++ b/yarn-project/end-to-end/src/e2e_fees/fees_test.ts @@ -146,7 +146,7 @@ export class FeesTest { this.feeRecipient = this.sequencerAddress; this.feeJuiceContract = await FeeJuiceContract.at(getCanonicalFeeJuice().address, this.aliceWallet); - const bobInstance = await this.bobWallet.getContractInstance(this.bobAddress); + const bobInstance = (await this.bobWallet.getContractMetadata(this.bobAddress)).contractInstance; if (!bobInstance) { throw new Error('Bob instance not found'); } @@ -222,7 +222,7 @@ export class FeesTest { 'fpc_setup', async context => { const feeJuiceContract = this.feeJuiceBridgeTestHarness.feeJuice; - expect(await context.pxe.isContractPubliclyDeployed(feeJuiceContract.address)).toBe(true); + expect((await context.pxe.getContractMetadata(feeJuiceContract.address)).isContractPubliclyDeployed).toBe(true); const bananaCoin = this.bananaCoin; const bananaFPC = await FPCContract.deploy(this.aliceWallet, bananaCoin.address, this.feeRecipient) diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index 488e7291bda4..4089568ddc52 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -519,7 +519,9 @@ export async function publicDeployAccounts( waitUntilProven = false, ) { const accountAddressesToDeploy = accountsToDeploy.map(a => ('address' in a ? a.address : a)); - const instances = await Promise.all(accountAddressesToDeploy.map(account => sender.getContractInstance(account))); + const instances = ( + await Promise.all(accountAddressesToDeploy.map(account => sender.getContractMetadata(account))) + ).map(contractMetadata => contractMetadata.contractInstance); const batch = new BatchCall(sender, [ (await registerContractClass(sender, SchnorrAccountContractArtifact)).request(), ...instances.map(instance => deployInstance(sender, instance!).request()), diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index db1825bb89c3..8e17a173d070 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -501,15 +501,19 @@ export async function ensureAccountsPubliclyDeployed(sender: Wallet, accountsToD const address = account.getAddress(); return { address, - deployed: await sender.isContractPubliclyDeployed(address), + deployed: (await sender.getContractMetadata(address)).isContractPubliclyDeployed, }; }), ); - const instances = await Promise.all( - accountsAndAddresses.filter(({ deployed }) => !deployed).map(({ address }) => sender.getContractInstance(address)), - ); + const instances = ( + await Promise.all( + accountsAndAddresses + .filter(({ deployed }) => !deployed) + .map(({ address }) => sender.getContractMetadata(address)), + ) + ).map(contractMetadata => contractMetadata.contractInstance); const contractClass = getContractClassFromArtifact(SchnorrAccountContractArtifact); - if (!(await sender.isContractClassPubliclyRegistered(contractClass.id))) { + if (!(await sender.getContractClassMetadata(contractClass.id, true)).isContractClassPubliclyRegistered) { await (await registerContractClass(sender, SchnorrAccountContractArtifact)).send().wait(); } const batch = new BatchCall(sender, [...instances.map(instance => deployInstance(sender, instance!).request())]); diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 201d69ba2b0b..03f66f939e55 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -158,13 +158,33 @@ export class PXEService implements PXE { return this.db.getContractInstance(address); } - public async getContractClass(id: Fr): Promise { + public async getContractClassMetadata( + id: Fr, + includeArtifact: boolean = false, + ): Promise<{ + contractClass: ContractClassWithId | undefined; + isContractClassPubliclyRegistered: boolean; + artifact: ContractArtifact | undefined; + }> { const artifact = await this.db.getContractArtifact(id); - return artifact && getContractClassFromArtifact(artifact); + + return { + contractClass: artifact && getContractClassFromArtifact(artifact), + isContractClassPubliclyRegistered: await this.#isContractClassPubliclyRegistered(id), + artifact: includeArtifact ? artifact : undefined, + }; } - public getContractArtifact(id: Fr): Promise { - return this.db.getContractArtifact(id); + public async getContractMetadata(address: AztecAddress): Promise<{ + contractInstance: ContractInstanceWithAddress | undefined; + isContractInitialized: boolean; + isContractPubliclyDeployed: boolean; + }> { + return { + contractInstance: await this.db.getContractInstance(address), + isContractInitialized: await this.#isContractInitialized(address), + isContractPubliclyDeployed: await this.#isContractPubliclyDeployed(address), + }; } public async registerAccount(secretKey: Fr, partialAddress: PartialAddress): Promise { @@ -228,12 +248,6 @@ export class PXEService implements PXE { ); } - public async getRegisteredAccount(address: AztecAddress): Promise { - const result = await this.getRegisteredAccounts(); - const account = result.find(r => r.address.equals(address)); - return Promise.resolve(account); - } - public async registerContractClass(artifact: ContractArtifact): Promise { const contractClassId = computeContractClassId(getContractClassFromArtifact(artifact)); await this.db.addContractArtifact(contractClassId, artifact); @@ -316,33 +330,6 @@ export class PXEService implements PXE { return Promise.all(extendedNotes); } - public async getOutgoingNotes(filter: OutgoingNotesFilter): Promise { - const noteDaos = await this.db.getOutgoingNotes(filter); - - const extendedNotes = noteDaos.map(async dao => { - let owner = filter.owner; - if (owner === undefined) { - const completeAddresses = (await this.db.getCompleteAddresses()).find(address => - address.publicKeys.masterOutgoingViewingPublicKey.equals(dao.ovpkM), - ); - if (completeAddresses === undefined) { - throw new Error(`Cannot find complete address for OvpkM ${dao.ovpkM.toString()}`); - } - owner = completeAddresses.address; - } - return new UniqueNote( - dao.note, - owner, - dao.contractAddress, - dao.storageSlot, - dao.noteTypeId, - dao.txHash, - dao.nonce, - ); - }); - return Promise.all(extendedNotes); - } - public async getL1ToL2MembershipWitness( contractAddress: AztecAddress, messageHash: Fr, @@ -879,15 +866,15 @@ export class PXEService implements PXE { return Promise.resolve(this.synchronizer.getSyncStatus()); } - public async isContractClassPubliclyRegistered(id: Fr): Promise { + async #isContractClassPubliclyRegistered(id: Fr): Promise { return !!(await this.node.getContractClass(id)); } - public async isContractPubliclyDeployed(address: AztecAddress): Promise { + async #isContractPubliclyDeployed(address: AztecAddress): Promise { return !!(await this.node.getContract(address)); } - public async isContractInitialized(address: AztecAddress): Promise { + async #isContractInitialized(address: AztecAddress): Promise { const initNullifier = siloNullifier(address, address.toField()); return !!(await this.node.getNullifierMembershipWitness('latest', initNullifier)); } @@ -914,7 +901,9 @@ export class PXEService implements PXE { const [keyPrefix, account] = this.keyStore.getKeyPrefixAndAccount(vpk); let secretKey = await this.keyStore.getMasterSecretKey(vpk); if (keyPrefix === 'iv') { - const registeredAccount = await this.getRegisteredAccount(account); + const registeredAccount = (await this.getRegisteredAccounts()).find(completeAddress => + completeAddress.address.equals(account), + ); if (!registeredAccount) { throw new Error('No registered account'); } diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index c5fc6219e010..a4aff1e327db 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -24,10 +24,6 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => // Check that the account is correctly registered using the getAccounts and getRecipients methods const accounts = await pxe.getRegisteredAccounts(); expect(accounts).toContainEqual(completeAddress); - - // Check that the account is correctly registered using the getAccount and getRecipient methods - const account = await pxe.getRegisteredAccount(completeAddress.address); - expect(account).toEqual(completeAddress); }); it('does not throw when registering the same account twice (just ignores the second attempt)', async () => { @@ -56,12 +52,12 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => const instance = randomContractInstanceWithAddress({ contractClassId }); await pxe.registerContractClass(artifact); - expect(await pxe.getContractClass(contractClassId)).toMatchObject( + expect((await pxe.getContractClassMetadata(contractClassId)).contractClass).toMatchObject( omit(contractClass, 'privateFunctionsRoot', 'publicBytecodeCommitment'), ); await pxe.registerContract({ instance }); - expect(await pxe.getContractInstance(instance.address)).toEqual(instance); + expect((await pxe.getContractMetadata(instance.address)).contractInstance).toEqual(instance); }); it('refuses to register a class with a mismatched address', async () => {