diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events/class_registered.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events/class_registered.nr index 3a5e11515ed6..7537442d287c 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events/class_registered.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/events/class_registered.nr @@ -1,29 +1,33 @@ use dep::aztec::protocol_types::{ constants::{ - MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE, + REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE, }, contract_class_id::ContractClassId, traits::Serialize, }; -// #[event] +// TODO(#10007): Use MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS instead +pub global MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS: u32 = 100; + pub struct ContractClassRegistered { contract_class_id: ContractClassId, version: Field, artifact_hash: Field, private_functions_root: Field, - packed_public_bytecode: [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS], + packed_public_bytecode: [Field; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS], } -impl Serialize for ContractClassRegistered { - fn serialize(self: Self) -> [Field; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5] { - let mut packed = [0; MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5]; +impl Serialize for ContractClassRegistered { + fn serialize( + self: Self, + ) -> [Field; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5] { + let mut packed = [0; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5]; packed[0] = REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE; packed[1] = self.contract_class_id.to_field(); packed[2] = self.version; packed[3] = self.artifact_hash; packed[4] = self.private_functions_root; - for i in 0..MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS { + for i in 0..MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS { packed[i + 5] = self.packed_public_bytecode[i]; } packed diff --git a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr index 8464b960fb01..1e8fb176fd10 100644 --- a/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr +++ b/noir-projects/noir-contracts/contracts/contract_class_registerer_contract/src/main.nr @@ -22,7 +22,9 @@ contract ContractClassRegisterer { }; use crate::events::{ - class_registered::ContractClassRegistered, + class_registered::{ + ContractClassRegistered, MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, + }, private_function_broadcasted::{ ClassPrivateFunctionBroadcasted, InnerPrivateFunction, PrivateFunction, }, @@ -81,13 +83,6 @@ contract ContractClassRegisterer { ); // Emit the contract class id as a nullifier to be able to prove that this class has been (not) registered - let event = ContractClassRegistered { - contract_class_id, - version: 1, - artifact_hash, - private_functions_root, - packed_public_bytecode, - }; context.push_nullifier(contract_class_id.to_field()); // Broadcast class info including public bytecode @@ -100,7 +95,24 @@ contract ContractClassRegisterer { public_bytecode_commitment, ], ); - emit_contract_class_log(&mut context, event.serialize()); + + // TODO(#10007): Drop this conditional and always emit the bytecode. We allow skipping the broadcast + // as a stopgap solution to allow txs to fit in Sepolia when we broadcast public bytecode. + if bytecode_length_in_fields <= MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS { + let mut event_public_bytecode = + [0; MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS]; + for i in 0..MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS { + event_public_bytecode[i] = packed_public_bytecode[i]; + } + let event = ContractClassRegistered { + contract_class_id, + version: 1, + artifact_hash, + private_functions_root, + packed_public_bytecode: event_public_bytecode, + }; + emit_contract_class_log(&mut context, event.serialize()); + } } #[private] diff --git a/yarn-project/archiver/package.json b/yarn-project/archiver/package.json index ff0dd170380f..8ce9df4a6323 100644 --- a/yarn-project/archiver/package.json +++ b/yarn-project/archiver/package.json @@ -71,6 +71,7 @@ "@aztec/foundation": "workspace:^", "@aztec/kv-store": "workspace:^", "@aztec/l1-artifacts": "workspace:^", + "@aztec/noir-contracts.js": "workspace:^", "@aztec/protocol-contracts": "workspace:^", "@aztec/telemetry-client": "workspace:^", "@aztec/types": "workspace:^", @@ -83,7 +84,6 @@ "ws": "^8.13.0" }, "devDependencies": { - "@aztec/noir-contracts.js": "workspace:^", "@jest/globals": "^29.5.0", "@types/debug": "^4.1.7", "@types/jest": "^29.5.0", diff --git a/yarn-project/archiver/src/archiver/archiver.ts b/yarn-project/archiver/src/archiver/archiver.ts index a2a10d8c7a26..b2d8887dd971 100644 --- a/yarn-project/archiver/src/archiver/archiver.ts +++ b/yarn-project/archiver/src/archiver/archiver.ts @@ -712,6 +712,12 @@ export class Archiver implements ArchiveSource { return this.store.getContractClassIds(); } + // TODO(#10007): Remove this method + async addContractClass(contractClass: ContractClassPublic): Promise { + await this.store.addContractClasses([contractClass], 0); + return; + } + addContractArtifact(address: AztecAddress, artifact: ContractArtifact): Promise { return this.store.addContractArtifact(address, artifact); } @@ -764,7 +770,6 @@ class ArchiverStoreHelper ArchiverDataStore, | 'addLogs' | 'deleteLogs' - | 'addContractClasses' | 'deleteContractClasses' | 'addContractInstances' | 'deleteContractInstances' @@ -775,6 +780,11 @@ class ArchiverStoreHelper constructor(private readonly store: ArchiverDataStore) {} + // TODO(#10007): Remove this method + addContractClasses(contractClasses: ContractClassPublic[], blockNum: number): Promise { + return this.store.addContractClasses(contractClasses, blockNum); + } + /** * Extracts and stores contract classes out of ContractClassRegistered events emitted by the class registerer contract. * @param allLogs - All logs emitted in a bunch of blocks. diff --git a/yarn-project/archiver/src/factory.ts b/yarn-project/archiver/src/factory.ts index e439ab370d59..28ed2ec035bb 100644 --- a/yarn-project/archiver/src/factory.ts +++ b/yarn-project/archiver/src/factory.ts @@ -1,9 +1,10 @@ import { type ArchiverApi, type Service } from '@aztec/circuit-types'; -import { type ContractClassPublic } from '@aztec/circuits.js'; +import { type ContractClassPublic, getContractClassFromArtifact } from '@aztec/circuits.js'; import { createDebugLogger } from '@aztec/foundation/log'; import { type Maybe } from '@aztec/foundation/types'; import { type DataStoreConfig } from '@aztec/kv-store/config'; import { createStore } from '@aztec/kv-store/utils'; +import { TokenBridgeContractArtifact, TokenContractArtifact } from '@aztec/noir-contracts.js'; import { getCanonicalProtocolContract, protocolContractNames } from '@aztec/protocol-contracts'; import { type TelemetryClient } from '@aztec/telemetry-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; @@ -21,14 +22,15 @@ export async function createArchiver( if (!config.archiverUrl) { const store = await createStore('archiver', config, createDebugLogger('aztec:archiver:lmdb')); const archiverStore = new KVArchiverDataStore(store, config.maxLogs); - await initWithProtocolContracts(archiverStore); + await registerProtocolContracts(archiverStore); + await registerCommonContracts(archiverStore); return Archiver.createAndSync(config, archiverStore, telemetry, opts.blockUntilSync); } else { return createArchiverClient(config.archiverUrl); } } -async function initWithProtocolContracts(store: KVArchiverDataStore) { +async function registerProtocolContracts(store: KVArchiverDataStore) { const blockNumber = 0; for (const name of protocolContractNames) { const contract = getCanonicalProtocolContract(name); @@ -42,3 +44,19 @@ async function initWithProtocolContracts(store: KVArchiverDataStore) { await store.addContractInstances([contract.instance], blockNumber); } } + +// TODO(#10007): Remove this method. We are explicitly registering these contracts +// here to ensure they are available to all nodes and all prover nodes, since the PXE +// was tweaked to automatically push contract classes to the node it is registered, +// but other nodes in the network may require the contract classes to be registered as well. +// TODO(#10007): Remove the dependency on noir-contracts.js from this package once we remove this. +async function registerCommonContracts(store: KVArchiverDataStore) { + const blockNumber = 0; + const artifacts = [TokenBridgeContractArtifact, TokenContractArtifact]; + const classes = artifacts.map(artifact => ({ + ...getContractClassFromArtifact(artifact), + privateFunctions: [], + unconstrainedFunctions: [], + })); + await store.addContractClasses(classes, blockNumber); +} diff --git a/yarn-project/archiver/tsconfig.json b/yarn-project/archiver/tsconfig.json index dbe9915c0107..901d60f657d1 100644 --- a/yarn-project/archiver/tsconfig.json +++ b/yarn-project/archiver/tsconfig.json @@ -24,6 +24,9 @@ { "path": "../l1-artifacts" }, + { + "path": "../noir-contracts.js" + }, { "path": "../protocol-contracts" }, @@ -32,9 +35,6 @@ }, { "path": "../types" - }, - { - "path": "../noir-contracts.js" } ], "include": ["src"] diff --git a/yarn-project/aztec-node/src/aztec-node/server.ts b/yarn-project/aztec-node/src/aztec-node/server.ts index f3cc8bda08f0..f61466cab697 100644 --- a/yarn-project/aztec-node/src/aztec-node/server.ts +++ b/yarn-project/aztec-node/src/aztec-node/server.ts @@ -815,7 +815,13 @@ export class AztecNodeService implements AztecNode { }); } + // TODO(#10007): Remove this method + public addContractClass(contractClass: ContractClassPublic): Promise { + return this.contractDataSource.addContractClass(contractClass); + } + public addContractArtifact(address: AztecAddress, artifact: ContractArtifact): Promise { + // TODO: Node should validate the artifact before accepting it return this.contractDataSource.addContractArtifact(address, artifact); } diff --git a/yarn-project/circuit-types/src/interfaces/archiver.test.ts b/yarn-project/circuit-types/src/interfaces/archiver.test.ts index b6b411c31770..6003a86e4270 100644 --- a/yarn-project/circuit-types/src/interfaces/archiver.test.ts +++ b/yarn-project/circuit-types/src/interfaces/archiver.test.ts @@ -232,6 +232,15 @@ describe('ArchiverApiSchema', () => { version: 1, }); }); + + it('addContractClass', async () => { + const contractClass = getContractClassFromArtifact(artifact); + await context.client.addContractClass({ + ...omit(contractClass, 'publicBytecodeCommitment'), + unconstrainedFunctions: [], + privateFunctions: [], + }); + }); }); class MockArchiver implements ArchiverApi { @@ -362,4 +371,7 @@ class MockArchiver implements ArchiverApi { expect(l1ToL2Message).toBeInstanceOf(Fr); return Promise.resolve(1n); } + addContractClass(_contractClass: ContractClassPublic): Promise { + return Promise.resolve(); + } } diff --git a/yarn-project/circuit-types/src/interfaces/archiver.ts b/yarn-project/circuit-types/src/interfaces/archiver.ts index 0dc118875aa7..4e32edb2b8fc 100644 --- a/yarn-project/circuit-types/src/interfaces/archiver.ts +++ b/yarn-project/circuit-types/src/interfaces/archiver.ts @@ -70,4 +70,6 @@ export const ArchiverApiSchema: ApiSchemaFor = { addContractArtifact: z.function().args(schemas.AztecAddress, ContractArtifactSchema).returns(z.void()), getL1ToL2Messages: z.function().args(schemas.BigInt).returns(z.array(schemas.Fr)), getL1ToL2MessageIndex: z.function().args(schemas.Fr).returns(schemas.BigInt.optional()), + // TODO(#10007): Remove this method + addContractClass: z.function().args(ContractClassPublicSchema).returns(z.void()), }; diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts index d415249c3f4b..2e810f65b3f0 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.test.ts @@ -313,6 +313,11 @@ describe('AztecNodeApiSchema', () => { const response = await context.client.getEpochProofQuotes(1n); expect(response).toEqual([expect.any(EpochProofQuote)]); }); + + it('addContractClass', async () => { + const contractClass = getContractClassFromArtifact(artifact); + await context.client.addContractClass({ ...contractClass, unconstrainedFunctions: [], privateFunctions: [] }); + }); }); class MockAztecNode implements AztecNode { @@ -538,4 +543,7 @@ class MockAztecNode implements AztecNode { expect(epoch).toEqual(1n); return Promise.resolve([EpochProofQuote.random()]); } + addContractClass(_contractClass: ContractClassPublic): Promise { + return Promise.resolve(); + } } diff --git a/yarn-project/circuit-types/src/interfaces/aztec-node.ts b/yarn-project/circuit-types/src/interfaces/aztec-node.ts index 91b7dd8d0ca8..b2a6c6a3149b 100644 --- a/yarn-project/circuit-types/src/interfaces/aztec-node.ts +++ b/yarn-project/circuit-types/src/interfaces/aztec-node.ts @@ -391,6 +391,13 @@ export interface AztecNode extends ProverCoordination { * @param epoch - The epoch for which to get the quotes */ getEpochProofQuotes(epoch: bigint): Promise; + + /** + * Adds a contract class bypassing the registerer. + * TODO(#10007): Remove this method. + * @param contractClass - The class to register. + */ + addContractClass(contractClass: ContractClassPublic): Promise; } export const AztecNodeApiSchema: ApiSchemaFor = { @@ -514,6 +521,9 @@ export const AztecNodeApiSchema: ApiSchemaFor = { addEpochProofQuote: z.function().args(EpochProofQuote.schema).returns(z.void()), getEpochProofQuotes: z.function().args(schemas.BigInt).returns(z.array(EpochProofQuote.schema)), + + // TODO(#10007): Remove this method + addContractClass: z.function().args(ContractClassPublicSchema).returns(z.void()), }; export function createAztecNodeClient(url: string, fetch = defaultFetch): AztecNode { diff --git a/yarn-project/circuits.js/src/contract/interfaces/contract_data_source.ts b/yarn-project/circuits.js/src/contract/interfaces/contract_data_source.ts index 6f545df85db8..b67afc8ac50e 100644 --- a/yarn-project/circuits.js/src/contract/interfaces/contract_data_source.ts +++ b/yarn-project/circuits.js/src/contract/interfaces/contract_data_source.ts @@ -26,6 +26,12 @@ export interface ContractDataSource { */ getContractClass(id: Fr): Promise; + /** + * Adds a contract class to the database. + * TODO(#10007): Remove this method + */ + addContractClass(contractClass: ContractClassPublic): Promise; + /** * Returns a publicly deployed contract instance given its address. * @param address - Address of the deployed contract. diff --git a/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts b/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts index 9908dfecbec9..a95a94df77ac 100644 --- a/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts +++ b/yarn-project/end-to-end/src/e2e_deploy_contract/contract_class_registration.test.ts @@ -5,8 +5,10 @@ import { type ContractClassWithId, type ContractInstanceWithAddress, type DebugLogger, + type FieldsOf, Fr, type PXE, + type TxReceipt, TxStatus, type Wallet, getContractClassFromArtifact, @@ -18,10 +20,10 @@ import { deployInstance, registerContractClass, } from '@aztec/aztec.js/deployment'; -import { type ContractClassIdPreimage, PublicKeys } from '@aztec/circuits.js'; +import { type ContractClassIdPreimage, PublicKeys, computeContractClassId } from '@aztec/circuits.js'; import { FunctionSelector, FunctionType } from '@aztec/foundation/abi'; import { writeTestData } from '@aztec/foundation/testing'; -import { StatefulTestContract } from '@aztec/noir-contracts.js'; +import { StatefulTestContract, TokenContractArtifact } from '@aztec/noir-contracts.js'; import { TestContract } from '@aztec/noir-contracts.js/Test'; import { DUPLICATE_NULLIFIER_ERROR } from '../fixtures/fixtures.js'; @@ -43,56 +45,74 @@ describe('e2e_deploy_contract contract class registration', () => { let artifact: ContractArtifact; let contractClass: ContractClassWithId & ContractClassIdPreimage; + let registrationTxReceipt: FieldsOf; beforeAll(async () => { artifact = StatefulTestContract.artifact; - await registerContractClass(wallet, artifact).then(c => c.send().wait()); + registrationTxReceipt = await registerContractClass(wallet, artifact).then(c => c.send().wait()); contractClass = getContractClassFromArtifact(artifact); - }); - it('registers the contract class on the node', async () => { - const registeredClass = await aztecNode.getContractClass(contractClass.id); - expect(registeredClass).toBeDefined(); - expect(registeredClass!.artifactHash.toString()).toEqual(contractClass.artifactHash.toString()); - expect(registeredClass!.privateFunctionsRoot.toString()).toEqual(contractClass.privateFunctionsRoot.toString()); - expect(registeredClass!.packedBytecode.toString('hex')).toEqual(contractClass.packedBytecode.toString('hex')); - expect(registeredClass!.publicFunctions).toEqual(contractClass.publicFunctions); - expect(registeredClass!.privateFunctions).toEqual([]); + // TODO(#10007) Remove this call. Node should get the bytecode from the event broadcast. + expect(await aztecNode.getContractClass(contractClass.id)).toBeUndefined(); + await aztecNode.addContractClass({ ...contractClass, privateFunctions: [], unconstrainedFunctions: [] }); }); - it('broadcasts a private function', async () => { - const constructorArtifact = artifact.functions.find(fn => fn.name == 'constructor'); - if (!constructorArtifact) { - // If this gets thrown you've probably modified the StatefulTestContract to no longer include constructor. - // If that's the case you should update this test to use a private function which fits into the bytecode size - // limit. - throw new Error('No constructor found in the StatefulTestContract artifact. Does it still exist?'); - } - const selector = FunctionSelector.fromNameAndParameters(constructorArtifact.name, constructorArtifact.parameters); - - const tx = await (await broadcastPrivateFunction(wallet, artifact, selector)).send().wait(); - const logs = await pxe.getContractClassLogs({ txHash: tx.txHash }); - const logData = logs.logs[0].log.data; - writeTestData('yarn-project/circuits.js/fixtures/PrivateFunctionBroadcastedEventData.hex', logData); - - const fetchedClass = await aztecNode.getContractClass(contractClass.id); - const fetchedFunction = fetchedClass!.privateFunctions[0]!; - expect(fetchedFunction).toBeDefined(); - expect(fetchedFunction.selector).toEqual(selector); - }); + describe('registering a contract class', () => { + // TODO(#10007) Remove this test. We should always broadcast public bytecode. + it('bypasses broadcast if exceeds bytecode limit for event size', async () => { + const logs = await aztecNode.getContractClassLogs({ txHash: registrationTxReceipt.txHash }); + expect(logs.logs.length).toEqual(0); + }); + + // TODO(#10007) Remove this test as well. + it('starts archiver with pre-registered common contracts', async () => { + const classId = computeContractClassId(getContractClassFromArtifact(TokenContractArtifact)); + expect(await aztecNode.getContractClass(classId)).not.toBeUndefined(); + }); - it('broadcasts an unconstrained function', async () => { - const functionArtifact = artifact.functions.find(fn => fn.functionType === FunctionType.UNCONSTRAINED)!; - const selector = FunctionSelector.fromNameAndParameters(functionArtifact); - const tx = await (await broadcastUnconstrainedFunction(wallet, artifact, selector)).send().wait(); - const logs = await pxe.getContractClassLogs({ txHash: tx.txHash }); - const logData = logs.logs[0].log.data; - writeTestData('yarn-project/circuits.js/fixtures/UnconstrainedFunctionBroadcastedEventData.hex', logData); - - const fetchedClass = await aztecNode.getContractClass(contractClass.id); - const fetchedFunction = fetchedClass!.unconstrainedFunctions[0]!; - expect(fetchedFunction).toBeDefined(); - expect(fetchedFunction.selector).toEqual(selector); + it('registers the contract class on the node', async () => { + const registeredClass = await aztecNode.getContractClass(contractClass.id); + expect(registeredClass).toBeDefined(); + expect(registeredClass!.artifactHash.toString()).toEqual(contractClass.artifactHash.toString()); + expect(registeredClass!.privateFunctionsRoot.toString()).toEqual(contractClass.privateFunctionsRoot.toString()); + expect(registeredClass!.packedBytecode.toString('hex')).toEqual(contractClass.packedBytecode.toString('hex')); + expect(registeredClass!.publicFunctions).toEqual(contractClass.publicFunctions); + expect(registeredClass!.privateFunctions).toEqual([]); + }); + + it('broadcasts a private function', async () => { + const constructorArtifact = artifact.functions.find(fn => fn.name == 'constructor'); + if (!constructorArtifact) { + // If this gets thrown you've probably modified the StatefulTestContract to no longer include constructor. + // If that's the case you should update this test to use a private function which fits into the bytecode size limit. + throw new Error('No constructor found in the StatefulTestContract artifact. Does it still exist?'); + } + const selector = FunctionSelector.fromNameAndParameters(constructorArtifact.name, constructorArtifact.parameters); + + const tx = await (await broadcastPrivateFunction(wallet, artifact, selector)).send().wait(); + const logs = await pxe.getContractClassLogs({ txHash: tx.txHash }); + const logData = logs.logs[0].log.data; + writeTestData('yarn-project/circuits.js/fixtures/PrivateFunctionBroadcastedEventData.hex', logData); + + const fetchedClass = await aztecNode.getContractClass(contractClass.id); + const fetchedFunction = fetchedClass!.privateFunctions[0]!; + expect(fetchedFunction).toBeDefined(); + expect(fetchedFunction.selector).toEqual(selector); + }); + + it('broadcasts an unconstrained function', async () => { + const functionArtifact = artifact.functions.find(fn => fn.functionType === FunctionType.UNCONSTRAINED)!; + const selector = FunctionSelector.fromNameAndParameters(functionArtifact); + const tx = await (await broadcastUnconstrainedFunction(wallet, artifact, selector)).send().wait(); + const logs = await pxe.getContractClassLogs({ txHash: tx.txHash }); + const logData = logs.logs[0].log.data; + writeTestData('yarn-project/circuits.js/fixtures/UnconstrainedFunctionBroadcastedEventData.hex', logData); + + const fetchedClass = await aztecNode.getContractClass(contractClass.id); + const fetchedFunction = fetchedClass!.unconstrainedFunctions[0]!; + expect(fetchedFunction).toBeDefined(); + expect(fetchedFunction.selector).toEqual(selector); + }); }); const testDeployingAnInstance = (how: string, deployFn: (toDeploy: ContractInstanceWithAddress) => Promise) => 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 e712e0e9ebb7..a1f6442a81ff 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 @@ -84,7 +84,8 @@ describe('e2e_deploy_contract legacy', () => { await expect(deployer.deploy().send({ contractAddressSalt }).wait()).rejects.toThrow(/dropped/); }); - it('should not deploy a contract which failed the public part of the execution', async () => { + // TODO(#10007): Reenable this test. + it.skip('should not deploy a contract which failed the public part of the execution', async () => { // This test requires at least another good transaction to go through in the same block as the bad one. const artifact = TokenContractArtifact; const initArgs = ['TokenName', 'TKN', 18] as const; diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 62e960817804..bbc78a4400f9 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -242,7 +242,8 @@ export class PXEService implements PXE { if (artifact) { // If the user provides an artifact, validate it against the expected class id and register it - const contractClassId = computeContractClassId(getContractClassFromArtifact(artifact)); + const contractClass = getContractClassFromArtifact(artifact); + const contractClassId = computeContractClassId(contractClass); if (!contractClassId.equals(instance.contractClassId)) { throw new Error( `Artifact does not match expected class id (computed ${contractClassId} but instance refers to ${instance.contractClassId})`, @@ -256,7 +257,12 @@ export class PXEService implements PXE { } await this.db.addContractArtifact(contractClassId, artifact); + + // TODO: PXE may not want to broadcast the artifact to the network await this.node.addContractArtifact(instance.address, artifact); + + // TODO(#10007): Node should get public contract class from the registration event, not from PXE registration + await this.node.addContractClass({ ...contractClass, privateFunctions: [], unconstrainedFunctions: [] }); } else { // Otherwise, make sure there is an artifact already registered for that class id artifact = await this.db.getContractArtifact(instance.contractClassId); diff --git a/yarn-project/txe/src/util/txe_public_contract_data_source.ts b/yarn-project/txe/src/util/txe_public_contract_data_source.ts index 437bed249cfc..1ae75b00a600 100644 --- a/yarn-project/txe/src/util/txe_public_contract_data_source.ts +++ b/yarn-project/txe/src/util/txe_public_contract_data_source.ts @@ -71,4 +71,10 @@ export class TXEPublicContractDataSource implements ContractDataSource { addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise { return this.txeOracle.addContractArtifact(contract); } + + // TODO(#10007): Remove this method. + addContractClass(_contractClass: ContractClassPublic): Promise { + // We don't really need to do anything for the txe here + return Promise.resolve(); + } }