Skip to content

Commit

Permalink
feat: verified contracts v0.1 (#233)
Browse files Browse the repository at this point in the history
also upgraded to aztec-packages 0.65.2
  • Loading branch information
FilipHarald authored Dec 9, 2024
1 parent 2b66c9e commit d38a74e
Show file tree
Hide file tree
Showing 31 changed files with 568 additions and 293 deletions.
9 changes: 8 additions & 1 deletion packages/backend-utils/src/parse-block.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,13 @@ export const parseBlock = (b: L2Block): ChicmozL2Block => {
return chicmozL2BlockSchema.parse({
hash: blockHash.toString(),
height: b.number,
...JSON.parse(JSON.stringify(blockWithTxEffectsHashesAdded)),
...blockWithTxEffectsHashesAdded,
header: {
...blockWithTxEffectsHashesAdded.header,
globalVariables: {
...blockWithTxEffectsHashesAdded.header.globalVariables,
coinbase: blockWithTxEffectsHashesAdded.header.globalVariables.coinbase.toString(),
},
},
});
};
8 changes: 4 additions & 4 deletions packages/types/src/aztec/l2TxEffect.ts
Original file line number Diff line number Diff line change
@@ -1,18 +1,18 @@
import { z } from "zod";
import { hexStringSchema } from "../general.js";
import { aztecAddressSchema, frNumberSchema, frSchema } from "./utils.js";
import { aztecAddressSchema, bufferSchema, frNumberSchema, frSchema } from "./utils.js";

export const noteEncryptedLogEntrySchema = z.object({
data: z.string(),
data: bufferSchema,
});

export const encryptedLogEntrySchema = z.object({
data: z.string(),
data: bufferSchema,
maskedContractAddress: frSchema,
});

export const unencryptedLogEntrySchema = z.object({
data: z.string(),
data: bufferSchema,
contractAddress: aztecAddressSchema,
});

Expand Down
1 change: 1 addition & 0 deletions packages/types/src/aztec/special.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ export const chicmozL2ContractInstanceDeluxeSchema = z.object({
...chicmozL2ContractInstanceDeployedEventSchema.shape,
...chicmozL2ContractClassRegisteredEventSchema.shape,
blockHeight: chicmozL2BlockSchema.shape.height.optional(),
aztecScoutVerified: z.boolean().optional(),
});

export type ChicmozL2ContractInstanceDeluxe = z.infer<
Expand Down
27 changes: 18 additions & 9 deletions packages/types/src/aztec/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,20 +10,13 @@ export type AztecAddress = {
toString(): string;
};

export type StringifiedAztecFr = {
type: "Fr";
value: `0x${string}`;
};

export type StringifiedAztecAddress = {
type: "AztecAddress";
value: `0x${string}`;
};

const frToHexString = (val: unknown) => {
if (!val) return val;
else if ((val as StringifiedAztecFr).value)
return (val as StringifiedAztecFr).value;
else if ((val as AztecFr).toString) return (val as AztecFr).toString();
else return val;
};
Expand All @@ -36,12 +29,28 @@ export const frSchema = z.preprocess(
.regex(/^0x[0-9a-fA-F]+$/)
);

export const frPointSchema = z.object({
type FrPoint = {
x: AztecFr;
y: AztecFr;
isInfinite: boolean;
kind: "point";
};

const frPointToObj = (val: unknown) => {
if (!val) return val;
else if ((val as FrPoint).x) return val;
else return val;
};

export const frPointSchema = z.preprocess(
frPointToObj,
z.object({
x: frSchema,
y: frSchema,
isInfinite: z.boolean(),
kind: z.enum(["point"]),
});
})
);

export const frNumberSchema = z.preprocess((val) => {
if (typeof val === "number") return val;
Expand Down
2 changes: 2 additions & 0 deletions services/event-cannon/src/cannon/index.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import { logger } from "../logger.js";
import { setup } from "./pxe.js";
import { run as deployAndInteractFunctionsVote } from "./scenarios/deploy-and-interact-vote-contract.js";
import { run as deploySimpleContract } from "./scenarios/simple-deploy-contract.js";
import { run as deploySimpleDefaultAccount } from "./scenarios/deploy-simple-default-account.js";
import { run as deployAndInteractTokenContract } from "./scenarios/deploy-and-interact-token-contract.js";
import { run as deploySimpleLog } from "./scenarios/deploy-and-run-simple-log.js";
Expand All @@ -25,6 +26,7 @@ export const start = async () => {
deploySimpleDefaultAccount,
deployAndInteractTokenContract,
deployAndInteractFunctionsVote,
deploySimpleContract,
deploySimpleLog,
l1L2PublicMessaging,
l1L2PrivateMessaging,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
import { DeploySentTx, waitForPXE } from "@aztec/aztec.js";
import { logger } from "../../logger.js";
import { getAztecNodeClient, getPxe, getWallets } from "../pxe.js";
import { deployContract } from "./utils/index.js";
import { EasyPrivateVotingContract } from "@aztec/noir-contracts.js";
import {
ContractClassRegisteredEvent,
ContractInstanceDeployedEvent,
} from "@aztec/circuits.js";
import { ProtocolContractAddress } from "@aztec/protocol-contracts";

export async function run() {
logger.info("===== SIMPLE DEPLOY CONTRACT =====");
const pxe = getPxe();
await waitForPXE(pxe);
const namedWallets = getWallets();

const deployerWallet = namedWallets.alice;
const votingAdmin = namedWallets.alice.getAddress();

const sentTx = EasyPrivateVotingContract.deploy(
deployerWallet,
votingAdmin
).send();

await deployContract({
contractLoggingName: "Voting Contract",
deployFn: (): DeploySentTx<EasyPrivateVotingContract> => sentTx,
});

const blockNumber = (await sentTx.getReceipt()).blockNumber;
const node = getAztecNodeClient();
if (blockNumber && blockNumber > 0) {
const b = await node.getBlock(blockNumber);
if (b) {
const encryptedBlockLogs = b.body.txEffects.flatMap((txEffect) =>
txEffect.encryptedLogs.unrollLogs()
);
const contractInstances =
ContractInstanceDeployedEvent.fromLogs(encryptedBlockLogs);

const contractClassLogs = b.body.txEffects.flatMap((txEffect) =>
txEffect.contractClassLogs.unrollLogs()
);
const contractClasses = ContractClassRegisteredEvent.fromLogs(
contractClassLogs,
ProtocolContractAddress.ContractClassRegisterer
);

logger.info(
JSON.stringify({
contractClasses,
contractInstances,
})
);
}
}
}
3 changes: 2 additions & 1 deletion services/event-cannon/src/cannon/scenarios/utils/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,9 @@ export const deployContract = async <T extends Contract>({
`📫 ${contractLoggingName} ${truncateHashString(hash)} (Deploying contract)`
);
const deployedContract = await contractTx.deployed();
const receipt = await contractTx.wait();
const addressString = deployedContract.address.toString();
logger.info(`⛏ ${contractLoggingName} deployed at: ${addressString}`);
logger.info(`⛏ ${contractLoggingName} deployed at: ${addressString} block: ${receipt.blockNumber}`);
if (broadcastWithWallet) {
await broadcastFunctions({
wallet: broadcastWithWallet,
Expand Down

Large diffs are not rendered by default.

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ CREATE TABLE IF NOT EXISTS "logs" (
"index" integer NOT NULL,
"tx_effect_to_logs_id" uuid NOT NULL,
"type" varchar(20) NOT NULL,
"data" varchar NOT NULL,
"data" "bytea" NOT NULL,
"masked_contract_address" varchar(66),
"contract_address" varchar(66)
);
Expand Down
4 changes: 2 additions & 2 deletions services/explorer-api/migrations/meta/0000_snapshot.json
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
{
"id": "af074cee-b3a6-4eff-9768-66ad1eace0e0",
"id": "4fe591f8-e500-430d-a332-4c1c8cde201c",
"prevId": "00000000-0000-0000-0000-000000000000",
"version": "7",
"dialect": "postgresql",
Expand Down Expand Up @@ -271,7 +271,7 @@
},
"data": {
"name": "data",
"type": "varchar",
"type": "bytea",
"primaryKey": false,
"notNull": true
},
Expand Down
4 changes: 2 additions & 2 deletions services/explorer-api/migrations/meta/_journal.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@
{
"idx": 0,
"version": "7",
"when": 1733146511848,
"tag": "0000_worried_impossible_man",
"when": 1733239184791,
"tag": "0000_dry_puppet_master",
"breakpoints": true
}
]
Expand Down
10 changes: 10 additions & 0 deletions services/explorer-api/src/constants.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,12 @@
export const CHAIN_NAME = "AZTEC";
export const SERVICE_NAME = "explorer-api";

export const DEFAULT_VERIFIED_CONTRACT_ADDRESSES_DEV = [
"0x11a81043f8c2cb2e95fa28e051f042a87e76c9e42d442188638eb2c07ae445b2", // Account address added by Sandbox
"0x17eafcd0961cc68c56b79305fa6fa8ee49bf8185b2bff279be84f3ceb1ae03ec", // Account address added by Sandbox
"0x12fb76c6e2ccbad0919c554c07257fc69993ddd9c799c62179345b5b82a95dd8", // Account address added by Sandbox
];

export const DEFAULT_VERIFIED_CONTRACT_ADDRESSES_PROD: string[] = [
// TODO: Add verified contract addresses for production
];
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,13 @@
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
/* eslint-disable @typescript-eslint/no-unsafe-argument */
import { ChicmozL2ContractInstanceDeluxe, chicmozL2ContractInstanceDeluxeSchema } from "@chicmoz-pkg/types";
import { VERIFIED_CONTRACT_ADDRESSES } from "../../../environment.js";

// eslint-disable-next-line @typescript-eslint/no-explicit-any
export const parseDeluxe = (contractClass: any, instance: any): ChicmozL2ContractInstanceDeluxe => {
return chicmozL2ContractInstanceDeluxeSchema.parse({
...contractClass,
aztecScoutVerified: VERIFIED_CONTRACT_ADDRESSES.some((address) => address === instance.address),
blockHash: instance.blockHash,
packedPublicBytecode: Buffer.from(contractClass.packedPublicBytecode),
address: instance.address,
Expand Down
18 changes: 17 additions & 1 deletion services/explorer-api/src/database/controllers/sign-of-life.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,12 @@
import { desc, eq, sql } from "drizzle-orm";
import { desc, eq, isNotNull, sql } from "drizzle-orm";
import { NodePgDatabase } from "drizzle-orm/node-postgres";
import { getDb as db } from "../../database/index.js";
import {
body,
l2Block,
logs,
txEffect,
txEffectToLogs,
} from "../../database/schema/l2block/index.js";
import { l2ContractInstanceDeployed, l2PrivateFunction, l2UnconstrainedFunction } from "../schema/index.js";

Expand Down Expand Up @@ -64,6 +66,20 @@ export const getABlockWithTxEffects = async () => {
};
};

export const getSomeTxEffectWithUnencryptedLogs = async () => {
const dbRes = await db()
.select({
hash: txEffectToLogs.txEffectHash,
})
.from(logs)
.where(isNotNull(logs.contractAddress))
.innerJoin(txEffectToLogs, eq(logs.txEffectToLogsId, txEffectToLogs.id))
.limit(10)
.execute();
if (dbRes.length === 0) return null;
return dbRes.map((row) => row.hash);
}

export const getABlockWithContractInstances = async () => {
const dbRes = await db()
.select({
Expand Down
3 changes: 2 additions & 1 deletion services/explorer-api/src/database/schema/l2block/body.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
varchar,
} from "drizzle-orm/pg-core";
import {
bufferType,
generateAztecAddressColumn,
generateFrColumn,
generateFrNumberColumn,
Expand Down Expand Up @@ -74,7 +75,7 @@ export const logs = pgTable("logs", {
.notNull()
.references(() => txEffectToLogs.id, { onDelete: "cascade" }),
type: varchar("type", { length: 20 }).notNull(), // 'noteEncrypted', 'encrypted', or 'unencrypted'
data: varchar("data").notNull(),
data: bufferType("data").notNull(),
maskedContractAddress: generateFrColumn("masked_contract_address"),
contractAddress: generateAztecAddressColumn("contract_address"),
});
Expand Down
21 changes: 17 additions & 4 deletions services/explorer-api/src/environment.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,29 @@
import { CHAIN_NAME } from "./constants.js";
export const NODE_ENV = process.env.NODE_ENV ?? "development";
import {
CHAIN_NAME,
DEFAULT_VERIFIED_CONTRACT_ADDRESSES_DEV,
DEFAULT_VERIFIED_CONTRACT_ADDRESSES_PROD,
} from "./constants.js";

const verifiedContractAddresses =
NODE_ENV === "production"
? DEFAULT_VERIFIED_CONTRACT_ADDRESSES_PROD
: DEFAULT_VERIFIED_CONTRACT_ADDRESSES_DEV;

export const PUBLIC_API_KEY = process.env.PUBLIC_API_KEY ?? "d1e2083a-660c-4314-a6f2-1d42f4b944f4";
export const VERIFIED_CONTRACT_ADDRESSES = verifiedContractAddresses

export const PUBLIC_API_KEY =
process.env.PUBLIC_API_KEY ?? "d1e2083a-660c-4314-a6f2-1d42f4b944f4";

export const CACHE_TTL_SECONDS = Number(process.env.CACHE_TTL) || 60;
export const CACHE_LATEST_TTL_SECONDS = Number(process.env.CACHE_LATEST_TTL) || 10;
export const CACHE_LATEST_TTL_SECONDS =
Number(process.env.CACHE_LATEST_TTL) || 10;
export const REDIS_HOST = process.env.REDIS_HOST ?? "redis-master";
export const REDIS_PORT = Number(process.env.REDIS_PORT) || 6379;

export const PORT = Number(process.env.PORT) || 5000;
export const BODY_LIMIT = process.env.BODY_LIMIT ?? "64kb";
export const PARAMETER_LIMIT = Number(process.env.PARAMETER_LIMIT) || 100;
export const NODE_ENV = process.env.NODE_ENV ?? "development";

export const DB_MAX_BLOCKS = 20;
export const DB_MAX_TX_EFFECTS = 20;
Expand Down
29 changes: 21 additions & 8 deletions services/explorer-api/src/event-handler/on-block/contracts.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,10 @@ const parseObjs = <T>(
const parsedObjs: T[] = [];
for (const obj of objs) {
try {
const parsed = parseFn(
JSON.parse(
JSON.stringify({
blockHash,
...obj,
})
)
);
const parsed = parseFn({
blockHash,
...obj,
});
parsedObjs.push(parsed);
} catch (e) {
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
Expand Down Expand Up @@ -78,6 +74,7 @@ export const storeContracts = async (b: L2Block, blockHash: string) => {
contractClassLogs,
ProtocolContractAddress.ContractClassRegisterer
);

const unencryptedBlockLogs = b.body.txEffects.flatMap((txEffect) =>
txEffect.unencryptedLogs.unrollLogs()
);
Expand All @@ -90,6 +87,22 @@ export const storeContracts = async (b: L2Block, blockHash: string) => {
ProtocolContractAddress.ContractClassRegisterer
);

if (
contractClasses.length > 0
) {
logger.info(
contractClasses.map((contractClass) => contractClass.contractClassId.toString())
);
}

if (
contractInstances.length > 0
) {
logger.info(
contractInstances.map((contractInstance) => `Contract instance: ${contractInstance.address.toString()} Contract class: ${contractInstance.contractClassId.toString()}`)
);
}

logger.info(
`📜 Parsing and storing ${contractClasses.length} contract classes and ${contractInstances.length} contract instances, ${privateFnEvents.length} private function events, and ${unconstrainedFnEvents.length} unconstrained function events`
);
Expand Down
Loading

0 comments on commit d38a74e

Please sign in to comment.