Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor: read function names from contract classes #10753

Merged
merged 5 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 4 additions & 12 deletions yarn-project/archiver/src/archiver/archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,6 @@ import {
isValidUnconstrainedFunctionMembershipProof,
} from '@aztec/circuits.js';
import { createEthereumChain } from '@aztec/ethereum';
import { type ContractArtifact } from '@aztec/foundation/abi';
import { type AztecAddress } from '@aztec/foundation/aztec-address';
import { type EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
Expand Down Expand Up @@ -766,12 +765,8 @@ export class Archiver implements ArchiveSource, Traceable {
return;
}

addContractArtifact(address: AztecAddress, artifact: ContractArtifact): Promise<void> {
return this.store.addContractArtifact(address, artifact);
}

getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined> {
return this.store.getContractArtifact(address);
registerContractFunctionNames(address: AztecAddress, names: Record<string, string>): Promise<void> {
return this.store.registerContractFunctionName(address, names);
}

getContractFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
Expand Down Expand Up @@ -1078,11 +1073,8 @@ class ArchiverStoreHelper
getContractClassIds(): Promise<Fr[]> {
return this.store.getContractClassIds();
}
addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise<void> {
return this.store.addContractArtifact(address, contract);
}
getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined> {
return this.store.getContractArtifact(address);
registerContractFunctionName(address: AztecAddress, names: Record<string, string>): Promise<void> {
return this.store.registerContractFunctionName(address, names);
}
getContractFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
return this.store.getContractFunctionName(address, selector);
Expand Down
6 changes: 2 additions & 4 deletions yarn-project/archiver/src/archiver/archiver_store.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import {
type PrivateLog,
type UnconstrainedFunctionWithMembershipProof,
} from '@aztec/circuits.js';
import { type ContractArtifact, type FunctionSelector } from '@aztec/foundation/abi';
import { type FunctionSelector } from '@aztec/foundation/abi';
import { type AztecAddress } from '@aztec/foundation/aztec-address';

import { type DataRetrieval } from './structs/data_retrieval.js';
Expand Down Expand Up @@ -261,12 +261,10 @@ export interface ArchiverDataStore {
/** Returns the list of all class ids known by the archiver. */
getContractClassIds(): Promise<Fr[]>;

addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise<void>;
getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined>;

// TODO: These function names are in memory only as they are for development/debugging. They require the full contract
// artifact supplied to the node out of band. This should be reviewed and potentially removed as part of
// the node api cleanup process.
registerContractFunctionName(address: AztecAddress, names: Record<string, string>): Promise<void>;
getContractFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined>;

/**
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import {
type PrivateLog,
type UnconstrainedFunctionWithMembershipProof,
} from '@aztec/circuits.js';
import { type ContractArtifact, FunctionSelector } from '@aztec/foundation/abi';
import { type FunctionSelector } from '@aztec/foundation/abi';
import { type AztecAddress } from '@aztec/foundation/aztec-address';
import { createLogger } from '@aztec/foundation/log';
import { type AztecKVStore } from '@aztec/kv-store';
Expand All @@ -26,7 +26,6 @@ import { type ArchiverDataStore, type ArchiverL1SynchPoint } from '../archiver_s
import { type DataRetrieval } from '../structs/data_retrieval.js';
import { type L1Published } from '../structs/published.js';
import { BlockStore } from './block_store.js';
import { ContractArtifactsStore } from './contract_artifacts_store.js';
import { ContractClassStore } from './contract_class_store.js';
import { ContractInstanceStore } from './contract_instance_store.js';
import { LogStore } from './log_store.js';
Expand All @@ -43,7 +42,6 @@ export class KVArchiverDataStore implements ArchiverDataStore {
#messageStore: MessageStore;
#contractClassStore: ContractClassStore;
#contractInstanceStore: ContractInstanceStore;
#contractArtifactStore: ContractArtifactsStore;
private functionNames = new Map<string, string>();

#log = createLogger('archiver:data-store');
Expand All @@ -54,27 +52,22 @@ export class KVArchiverDataStore implements ArchiverDataStore {
this.#messageStore = new MessageStore(db);
this.#contractClassStore = new ContractClassStore(db);
this.#contractInstanceStore = new ContractInstanceStore(db);
this.#contractArtifactStore = new ContractArtifactsStore(db);
this.#nullifierStore = new NullifierStore(db);
}

getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined> {
return Promise.resolve(this.#contractArtifactStore.getContractArtifact(address));
}

// TODO: These function names are in memory only as they are for development/debugging. They require the full contract
// artifact supplied to the node out of band. This should be reviewed and potentially removed as part of
// the node api cleanup process.
getContractFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
getContractFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
return Promise.resolve(this.functionNames.get(selector.toString()));
}

async addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise<void> {
await this.#contractArtifactStore.addContractArtifact(address, contract);
// Building tup this map of selectors to function names save expensive re-hydration of contract artifacts later
contract.functions.forEach(f => {
this.functionNames.set(FunctionSelector.fromNameAndParameters(f.name, f.parameters).toString(), f.name);
});
registerContractFunctionName(_address: AztecAddress, names: Record<string, string>): Promise<void> {
for (const [selector, name] of Object.entries(names)) {
this.functionNames.set(selector, name);
}

return Promise.resolve();
}

getContractClass(id: Fr): Promise<ContractClassPublic | undefined> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import {
type PrivateLog,
type UnconstrainedFunctionWithMembershipProof,
} from '@aztec/circuits.js';
import { type ContractArtifact, FunctionSelector } from '@aztec/foundation/abi';
import { type FunctionSelector } from '@aztec/foundation/abi';
import { type AztecAddress } from '@aztec/foundation/aztec-address';
import { createLogger } from '@aztec/foundation/log';

Expand Down Expand Up @@ -68,8 +68,6 @@ export class MemoryArchiverStore implements ArchiverDataStore {
*/
private l1ToL2Messages = new L1ToL2MessageStore();

private contractArtifacts: Map<string, ContractArtifact> = new Map();

private contractClasses: Map<string, ContractClassPublicWithBlockNumber> = new Map();

private bytecodeCommitments: Map<string, Fr> = new Map();
Expand All @@ -86,6 +84,8 @@ export class MemoryArchiverStore implements ArchiverDataStore {
private lastProvenL2BlockNumber: number = 0;
private lastProvenL2EpochNumber: number = 0;

private functionNames = new Map<string, string>();

#log = createLogger('archiver:data-store');

constructor(
Expand Down Expand Up @@ -730,26 +730,16 @@ export class MemoryArchiverStore implements ArchiverDataStore {
});
}

public addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise<void> {
this.contractArtifacts.set(address.toString(), contract);
return Promise.resolve();
}

public getContractArtifact(address: AztecAddress): Promise<ContractArtifact | undefined> {
return Promise.resolve(this.contractArtifacts.get(address.toString()));
public getContractFunctionName(_address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
return Promise.resolve(this.functionNames.get(selector.toString()));
}

async getContractFunctionName(address: AztecAddress, selector: FunctionSelector): Promise<string | undefined> {
const artifact = await this.getContractArtifact(address);

if (!artifact) {
return undefined;
public registerContractFunctionName(_address: AztecAddress, names: Record<string, string>): Promise<void> {
for (const [selector, name] of Object.entries(names)) {
this.functionNames.set(selector, name);
}

const func = artifact.functions.find(f =>
FunctionSelector.fromNameAndParameters({ name: f.name, parameters: f.parameters }).equals(selector),
);
return Promise.resolve(func?.name);
return Promise.resolve();
}

public estimateSize(): { mappingSize: number; actualSize: number; numItems: number } {
Expand Down
11 changes: 10 additions & 1 deletion yarn-project/archiver/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import {
computePublicBytecodeCommitment,
getContractClassFromArtifact,
} from '@aztec/circuits.js';
import { FunctionSelector, FunctionType } from '@aztec/foundation/abi';
import { createLogger } from '@aztec/foundation/log';
import { type Maybe } from '@aztec/foundation/types';
import { type DataStoreConfig } from '@aztec/kv-store/config';
Expand Down Expand Up @@ -45,7 +46,15 @@ async function registerProtocolContracts(store: KVArchiverDataStore) {
privateFunctions: [],
unconstrainedFunctions: [],
};
await store.addContractArtifact(contract.address, contract.artifact);

const functionNames: Record<string, string> = {};
for (const fn of contract.artifact.functions) {
if (fn.functionType === FunctionType.PUBLIC) {
functionNames[FunctionSelector.fromNameAndParameters(fn.name, fn.parameters).toString()] = fn.name;
}
}

await store.registerContractFunctionName(contract.address, functionNames);
const bytecodeCommitment = computePublicBytecodeCommitment(contractClassPublic.packedBytecode);
await store.addContractClasses([contractClassPublic], [bytecodeCommitment], blockNumber);
await store.addContractInstances([contract.instance], blockNumber);
Expand Down
7 changes: 2 additions & 5 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ import {
} from '@aztec/circuits.js';
import { computePublicDataTreeLeafSlot } from '@aztec/circuits.js/hash';
import { type L1ContractAddresses, createEthereumChain } from '@aztec/ethereum';
import { type ContractArtifact } from '@aztec/foundation/abi';
import { AztecAddress } from '@aztec/foundation/aztec-address';
import { padArrayEnd } from '@aztec/foundation/collection';
import { type Logger, createLogger } from '@aztec/foundation/log';
Expand Down Expand Up @@ -901,10 +900,8 @@ export class AztecNodeService implements AztecNode, Traceable {
return this.contractDataSource.addContractClass(contractClass);
}

public addContractArtifact(address: AztecAddress, artifact: ContractArtifact): Promise<void> {
this.log.info(`Adding contract artifact ${artifact.name} for ${address.toString()} via API`);
// TODO: Node should validate the artifact before accepting it
return this.contractDataSource.addContractArtifact(address, artifact);
public registerContractFunctionNames(_address: AztecAddress, names: Record<string, string>): Promise<void> {
return this.contractDataSource.registerContractFunctionNames(_address, names);
}

public flushTxs(): Promise<void> {
Expand Down
17 changes: 6 additions & 11 deletions yarn-project/circuit-types/src/interfaces/archiver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { type JsonRpcTestContext, createJsonRpcTestSetup } from '@aztec/foundati
import { fileURLToPath } from '@aztec/foundation/url';
import { loadContractArtifact } from '@aztec/types/abi';

import { deepStrictEqual } from 'assert';
import { readFileSync } from 'fs';
import omit from 'lodash.omit';
import { resolve } from 'path';
Expand Down Expand Up @@ -223,15 +222,12 @@ describe('ArchiverApiSchema', () => {
expect(result).toBe(1n);
});

it('getContractArtifact', async () => {
const result = await context.client.getContractArtifact(AztecAddress.random());
deepStrictEqual(result, artifact);
it('registerContractFunctionNames', async () => {
await context.client.registerContractFunctionNames(AztecAddress.random(), {
[FunctionSelector.random().toString()]: 'test_fn',
});
});

it('addContractArtifact', async () => {
await context.client.addContractArtifact(AztecAddress.random(), artifact);
}, 20_000);

it('getContract', async () => {
const address = AztecAddress.random();
const result = await context.client.getContract(address);
Expand Down Expand Up @@ -378,10 +374,9 @@ class MockArchiver implements ArchiverApi {
expect(address).toBeInstanceOf(AztecAddress);
return Promise.resolve(this.artifact);
}
addContractArtifact(address: AztecAddress, contract: ContractArtifact): Promise<void> {
registerContractFunctionNames(address: AztecAddress, names: Record<string, string>): Promise<void> {
expect(address).toBeInstanceOf(AztecAddress);
// We use node's native assertion because jest's is too slow
deepStrictEqual(contract, this.artifact);
expect(names).toEqual(expect.any(Object));
return Promise.resolve();
}
getL1ToL2Messages(blockNumber: bigint): Promise<Fr[]> {
Expand Down
7 changes: 4 additions & 3 deletions yarn-project/circuit-types/src/interfaces/archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import {
PrivateLog,
PublicFunctionSchema,
} from '@aztec/circuits.js';
import { ContractArtifactSchema } from '@aztec/foundation/abi';
import { type ApiSchemaFor, optional, schemas } from '@aztec/foundation/schemas';

import { z } from 'zod';
Expand Down Expand Up @@ -69,8 +68,10 @@ export const ArchiverApiSchema: ApiSchemaFor<ArchiverApi> = {
getBytecodeCommitment: z.function().args(schemas.Fr).returns(schemas.Fr),
getContract: z.function().args(schemas.AztecAddress).returns(ContractInstanceWithAddressSchema.optional()),
getContractClassIds: z.function().args().returns(z.array(schemas.Fr)),
getContractArtifact: z.function().args(schemas.AztecAddress).returns(ContractArtifactSchema.optional()),
addContractArtifact: z.function().args(schemas.AztecAddress, ContractArtifactSchema).returns(z.void()),
registerContractFunctionNames: z
.function()
.args(schemas.AztecAddress, z.record(z.string(), z.string()))
.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
Expand Down
15 changes: 7 additions & 8 deletions yarn-project/circuit-types/src/interfaces/aztec-node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,13 +19,12 @@ import {
getContractClassFromArtifact,
} from '@aztec/circuits.js';
import { type L1ContractAddresses, L1ContractsNames } from '@aztec/ethereum';
import { type ContractArtifact } from '@aztec/foundation/abi';
import { type ContractArtifact, FunctionSelector } from '@aztec/foundation/abi';
import { memoize } from '@aztec/foundation/decorators';
import { type JsonRpcTestContext, createJsonRpcTestSetup } from '@aztec/foundation/json-rpc/test';
import { fileURLToPath } from '@aztec/foundation/url';
import { loadContractArtifact } from '@aztec/types/abi';

import { deepStrictEqual } from 'assert';
import { readFileSync } from 'fs';
import omit from 'lodash.omit';
import times from 'lodash.times';
Expand Down Expand Up @@ -224,9 +223,11 @@ describe('AztecNodeApiSchema', () => {
expect(response).toEqual(Object.fromEntries(ProtocolContractsNames.map(name => [name, expect.any(AztecAddress)])));
});

it('addContractArtifact', async () => {
await context.client.addContractArtifact(AztecAddress.random(), artifact);
}, 20_000);
it('registerContractFunctionNames', async () => {
await context.client.registerContractFunctionNames(AztecAddress.random(), {
[FunctionSelector.random().toString()]: 'test_fn',
});
});

it('getPrivateLogs', async () => {
const response = await context.client.getPrivateLogs(1, 1);
Expand Down Expand Up @@ -505,9 +506,7 @@ class MockAztecNode implements AztecNode {
) as ProtocolContractAddresses,
);
}
addContractArtifact(address: AztecAddress, artifact: ContractArtifact): Promise<void> {
expect(address).toBeInstanceOf(AztecAddress);
deepStrictEqual(artifact, this.artifact);
registerContractFunctionNames(_address: AztecAddress, _names: Record<string, string>): Promise<void> {
return Promise.resolve();
}
getPrivateLogs(_from: number, _limit: number): Promise<PrivateLog[]> {
Expand Down
Loading
Loading