Skip to content

Commit

Permalink
Merge 8e6396d into a2c0701
Browse files Browse the repository at this point in the history
  • Loading branch information
spalladino authored Nov 20, 2024
2 parents a2c0701 + 8e6396d commit 1e19c20
Show file tree
Hide file tree
Showing 16 changed files with 191 additions and 73 deletions.
Original file line number Diff line number Diff line change
@@ -1,29 +1,30 @@
use dep::aztec::protocol_types::{
constants::{
MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS, REGISTERER_CONTRACT_CLASS_REGISTERED_MAGIC_VALUE,
},
contract_class_id::ContractClassId,
constants::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<MAX_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5> 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<MAX_BROADCASTEABLE_PACKED_PUBLIC_BYTECODE_SIZE_IN_FIELDS + 5> 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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
},
Expand Down Expand Up @@ -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
Expand All @@ -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]
Expand Down
2 changes: 1 addition & 1 deletion yarn-project/archiver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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:^",
Expand All @@ -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",
Expand Down
12 changes: 11 additions & 1 deletion yarn-project/archiver/src/archiver/archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -712,6 +712,12 @@ export class Archiver implements ArchiveSource {
return this.store.getContractClassIds();
}

// TODO(#10007): Remove this method
async addContractClass(contractClass: ContractClassPublic): Promise<void> {
await this.store.addContractClasses([contractClass], 0);
return;
}

addContractArtifact(address: AztecAddress, artifact: ContractArtifact): Promise<void> {
return this.store.addContractArtifact(address, artifact);
}
Expand Down Expand Up @@ -764,7 +770,6 @@ class ArchiverStoreHelper
ArchiverDataStore,
| 'addLogs'
| 'deleteLogs'
| 'addContractClasses'
| 'deleteContractClasses'
| 'addContractInstances'
| 'deleteContractInstances'
Expand All @@ -775,6 +780,11 @@ class ArchiverStoreHelper

constructor(private readonly store: ArchiverDataStore) {}

// TODO(#10007): Remove this method
addContractClasses(contractClasses: ContractClassPublic[], blockNum: number): Promise<boolean> {
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.
Expand Down
24 changes: 21 additions & 3 deletions yarn-project/archiver/src/factory.ts
Original file line number Diff line number Diff line change
@@ -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';
Expand All @@ -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);
Expand All @@ -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);
}
6 changes: 3 additions & 3 deletions yarn-project/archiver/tsconfig.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@
{
"path": "../l1-artifacts"
},
{
"path": "../noir-contracts.js"
},
{
"path": "../protocol-contracts"
},
Expand All @@ -32,9 +35,6 @@
},
{
"path": "../types"
},
{
"path": "../noir-contracts.js"
}
],
"include": ["src"]
Expand Down
6 changes: 6 additions & 0 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -812,7 +812,13 @@ export class AztecNodeService implements AztecNode {
});
}

// TODO(#10007): Remove this method
public addContractClass(contractClass: ContractClassPublic): Promise<void> {
return this.contractDataSource.addContractClass(contractClass);
}

public addContractArtifact(address: AztecAddress, artifact: ContractArtifact): Promise<void> {
// TODO: Node should validate the artifact before accepting it
return this.contractDataSource.addContractArtifact(address, artifact);
}

Expand Down
12 changes: 12 additions & 0 deletions yarn-project/circuit-types/src/interfaces/archiver.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -362,4 +371,7 @@ class MockArchiver implements ArchiverApi {
expect(l1ToL2Message).toBeInstanceOf(Fr);
return Promise.resolve(1n);
}
addContractClass(_contractClass: ContractClassPublic): Promise<void> {
return Promise.resolve();
}
}
2 changes: 2 additions & 0 deletions yarn-project/circuit-types/src/interfaces/archiver.ts
Original file line number Diff line number Diff line change
Expand Up @@ -70,4 +70,6 @@ export const ArchiverApiSchema: ApiSchemaFor<ArchiverApi> = {
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()),
};
8 changes: 8 additions & 0 deletions yarn-project/circuit-types/src/interfaces/aztec-node.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -538,4 +543,7 @@ class MockAztecNode implements AztecNode {
expect(epoch).toEqual(1n);
return Promise.resolve([EpochProofQuote.random()]);
}
addContractClass(_contractClass: ContractClassPublic): Promise<void> {
return Promise.resolve();
}
}
10 changes: 10 additions & 0 deletions yarn-project/circuit-types/src/interfaces/aztec-node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -391,6 +391,13 @@ export interface AztecNode extends ProverCoordination {
* @param epoch - The epoch for which to get the quotes
*/
getEpochProofQuotes(epoch: bigint): Promise<EpochProofQuote[]>;

/**
* Adds a contract class bypassing the registerer.
* TODO(#10007): Remove this method.
* @param contractClass - The class to register.
*/
addContractClass(contractClass: ContractClassPublic): Promise<void>;
}

export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
Expand Down Expand Up @@ -514,6 +521,9 @@ export const AztecNodeApiSchema: ApiSchemaFor<AztecNode> = {
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 {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,12 @@ export interface ContractDataSource {
*/
getContractClass(id: Fr): Promise<ContractClassPublic | undefined>;

/**
* Adds a contract class to the database.
* TODO(#10007): Remove this method
*/
addContractClass(contractClass: ContractClassPublic): Promise<void>;

/**
* Returns a publicly deployed contract instance given its address.
* @param address - Address of the deployed contract.
Expand Down
Loading

0 comments on commit 1e19c20

Please sign in to comment.