Skip to content

Commit

Permalink
init
Browse files Browse the repository at this point in the history
  • Loading branch information
sklppy88 committed Dec 12, 2024
1 parent 15a7891 commit 1ec02c7
Show file tree
Hide file tree
Showing 16 changed files with 165 additions and 149 deletions.
6 changes: 5 additions & 1 deletion yarn-project/aztec.js/src/contract/contract.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,11 @@ describe('Contract Class', () => {
wallet = mock<Wallet>();
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);
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/contract/contract.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<Contract> {
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`);
}
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/aztec.js/src/contract/deploy_method.ts
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ export class DeployMethod<TContract extends ContractBase = Contract> 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()}`,
);
Expand Down
26 changes: 8 additions & 18 deletions yarn-project/aztec.js/src/wallet/base_wallet.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import {
type AuthWitness,
ContractClassMetadata,
ContractMetadata,
type EventMetadataDefinition,
type ExtendedNote,
type GetUnencryptedLogsResponse,
Expand Down Expand Up @@ -66,15 +68,6 @@ export abstract class BaseWallet implements Wallet {
getAddress() {
return this.getCompleteAddress().address;
}
getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
return this.pxe.getContractInstance(address);
}
getContractClass(id: Fr): Promise<ContractClassWithId | undefined> {
return this.pxe.getContractClass(id);
}
getContractArtifact(id: Fr): Promise<ContractArtifact | undefined> {
return this.pxe.getContractArtifact(id);
}
addCapsule(capsule: Fr[]): Promise<void> {
return this.pxe.addCapsule(capsule);
}
Expand Down Expand Up @@ -179,18 +172,15 @@ export abstract class BaseWallet implements Wallet {
getAuthWitness(messageHash: Fr) {
return this.pxe.getAuthWitness(messageHash);
}
isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
return this.pxe.isContractClassPubliclyRegistered(id);
}
isContractPubliclyDeployed(address: AztecAddress): Promise<boolean> {
return this.pxe.isContractPubliclyDeployed(address);
}
isContractInitialized(address: AztecAddress): Promise<boolean> {
return this.pxe.isContractInitialized(address);
}
getPXEInfo(): Promise<PXEInfo> {
return this.pxe.getPXEInfo();
}
getContractClassMetadata(id: Fr, includeArtifact: boolean = false): Promise<ContractClassMetadata> {
return this.pxe.getContractClassMetadata(id, includeArtifact);
}
getContractMetadata(address: AztecAddress): Promise<ContractMetadata> {
return this.pxe.getContractMetadata(address);
}
getEncryptedEvents<T>(
event: EventMetadataDefinition,
from: number,
Expand Down
4 changes: 2 additions & 2 deletions yarn-project/bot/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down Expand Up @@ -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 {
Expand Down
82 changes: 35 additions & 47 deletions yarn-project/circuit-types/src/interfaces/pxe.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -263,35 +270,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 () => {
Expand Down Expand Up @@ -505,30 +501,22 @@ class MockPXE implements PXE {
blocks: 1,
});
}
getContractInstance(address: AztecAddress): Promise<ContractInstanceWithAddress | undefined> {
expect(address).toEqual(this.address);
return Promise.resolve(this.instance);
}
getContractClass(id: Fr): Promise<ContractClassWithId | undefined> {
getContractClassMetadata(id: Fr, includeArtifact: boolean = false): Promise<ContractClassMetadata> {
expect(id).toBeInstanceOf(Fr);
const contractClass = getContractClassFromArtifact(this.artifact);
return Promise.resolve(contractClass);
}
getContractArtifact(id: Fr): Promise<ContractArtifact | undefined> {
expect(id).toBeInstanceOf(Fr);
return Promise.resolve(this.artifact);
}
isContractClassPubliclyRegistered(id: Fr): Promise<boolean> {
expect(id).toBeInstanceOf(Fr);
return Promise.resolve(true);
}
isContractPubliclyDeployed(address: AztecAddress): Promise<boolean> {
expect(address).toEqual(this.address);
return Promise.resolve(true);
return Promise.resolve({
contractClass,
isContractClassPubliclyRegistered: true,
artifact: includeArtifact ? this.artifact : undefined,
});
}
isContractInitialized(address: AztecAddress): Promise<boolean> {
getContractMetadata(address: AztecAddress): Promise<ContractMetadata> {
expect(address).toEqual(this.address);
return Promise.resolve(true);
return Promise.resolve({
contractInstance: this.instance,
isContractInitialized: true,
isContractPubliclyDeployed: true,
});
}
getEncryptedEvents<T>(
_eventMetadata: EventMetadataDefinition,
Expand Down
91 changes: 43 additions & 48 deletions yarn-project/circuit-types/src/interfaces/pxe.ts
Original file line number Diff line number Diff line change
Expand Up @@ -359,49 +359,33 @@ export interface PXE {
getSyncStatus(): Promise<SyncStatus>;

/**
* 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<ContractInstanceWithAddress | undefined>;
getContractMetadata(address: AztecAddress): Promise<ContractMetadata>;

/**
* 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<ContractClassWithId | undefined>;

/**
* Returns the contract artifact associated to a contract class.
* @param id - Identifier of the class.
*/
getContractArtifact(id: Fr): Promise<ContractArtifact | undefined>;

/**
* 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<boolean>;

/**
* 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<boolean>;

/**
* 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<boolean>;
getContractClassMetadata(id: Fr, includeArtifact?: boolean): Promise<ContractClassMetadata>;

/**
* Returns the enctypred events given search parameters.
Expand Down Expand Up @@ -455,6 +439,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<ContractMetadata>;

const ContractClassMetadataSchema = z.object({
contractClass: z.union([ContractClassWithIdSchema, z.undefined()]),
isContractClassPubliclyRegistered: z.boolean(),
artifact: z.union([ContractArtifactSchema, z.undefined()]),
}) satisfies ZodFor<ContractClassMetadata>;

const PXEInfoSchema = z.object({
pxeVersion: z.string(),
protocolContractAddresses: ProtocolContractAddressesSchema,
Expand Down Expand Up @@ -529,21 +537,8 @@ export const PXESchema: ApiSchemaFor<PXE> = {
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))
Expand Down
11 changes: 7 additions & 4 deletions yarn-project/cli/src/cmds/pxe/get_contract_data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
18 changes: 12 additions & 6 deletions yarn-project/cli/src/utils/inspect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -182,17 +182,23 @@ type ArtifactMap = Record<string, ContractArtifactWithClassId>;
type ContractArtifactWithClassId = ContractArtifact & { classId: Fr };
async function getKnownArtifacts(pxe: PXE): Promise<ArtifactMap> {
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<string, ContractArtifactWithClassId> = {};
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;
}
Expand Down
3 changes: 2 additions & 1 deletion yarn-project/end-to-end/src/e2e_block_building.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,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));
});
Expand Down
Loading

0 comments on commit 1ec02c7

Please sign in to comment.