Skip to content
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
5 changes: 4 additions & 1 deletion yarn-project/archiver/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@
"name": "@aztec/archiver",
"version": "0.1.0",
"type": "module",
"exports": "./dest/index.js",
"exports": {
".": "./dest/index.js",
"./data-retrieval": "./dest/archiver/data_retrieval.js"
},
"typedocOptions": {
"entryPoints": [
"./src/index.ts"
Expand Down
27 changes: 25 additions & 2 deletions yarn-project/archiver/src/archiver/data_retrieval.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
import { type Body, type InboxLeaf } from '@aztec/circuit-types';
import { type AppendOnlyTreeSnapshot, Fr, type Header } from '@aztec/circuits.js';
import { type AppendOnlyTreeSnapshot, Fr, type Header, type Proof } from '@aztec/circuits.js';
import { type EthAddress } from '@aztec/foundation/eth-address';
import { type DebugLogger, createDebugLogger } from '@aztec/foundation/log';
import { RollupAbi } from '@aztec/l1-artifacts';

import { type PublicClient, getAbiItem } from 'viem';

import {
getBlockProofFromSubmitProofTx,
getL2BlockProcessedLogs,
getMessageSentLogs,
getTxsPublishedLogs,
Expand Down Expand Up @@ -147,7 +148,7 @@ export async function retrieveL2ProofVerifiedEvents(
rollupAddress: EthAddress,
searchStartBlock: bigint,
searchEndBlock?: bigint,
): Promise<{ l1BlockNumber: bigint; l2BlockNumber: bigint; proverId: Fr }[]> {
): Promise<{ l1BlockNumber: bigint; l2BlockNumber: bigint; proverId: Fr; txHash: `0x${string}` }[]> {
const logs = await publicClient.getLogs({
address: rollupAddress.toString(),
fromBlock: searchStartBlock,
Expand All @@ -160,5 +161,27 @@ export async function retrieveL2ProofVerifiedEvents(
l1BlockNumber: log.blockNumber,
l2BlockNumber: log.args.blockNumber,
proverId: Fr.fromString(log.args.proverId),
txHash: log.transactionHash,
}));
}

/** Retrieve submitted proofs from the rollup contract */
export async function retrieveL2ProofsFromRollup(
publicClient: PublicClient,
rollupAddress: EthAddress,
searchStartBlock: bigint,
searchEndBlock?: bigint,
): Promise<DataRetrieval<{ proof: Proof; proverId: Fr; l2BlockNumber: bigint; txHash: `0x${string}` }>> {
const logs = await retrieveL2ProofVerifiedEvents(publicClient, rollupAddress, searchStartBlock, searchEndBlock);
const retrievedData: { proof: Proof; proverId: Fr; l2BlockNumber: bigint; txHash: `0x${string}` }[] = [];
const lastProcessedL1BlockNumber = logs.length > 0 ? logs.at(-1)!.l1BlockNumber : searchStartBlock - 1n;

for (const { txHash, proverId, l2BlockNumber } of logs) {
const proofData = await getBlockProofFromSubmitProofTx(publicClient, txHash, l2BlockNumber, proverId);
retrievedData.push({ proof: proofData.proof, proverId: proofData.proverId, l2BlockNumber, txHash });
}
return {
retrievedData,
lastProcessedL1BlockNumber,
};
}
56 changes: 55 additions & 1 deletion yarn-project/archiver/src/archiver/eth_log_handlers.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Body, InboxLeaf } from '@aztec/circuit-types';
import { AppendOnlyTreeSnapshot, Header } from '@aztec/circuits.js';
import { AppendOnlyTreeSnapshot, Header, Proof } from '@aztec/circuits.js';
import { type EthAddress } from '@aztec/foundation/eth-address';
import { Fr } from '@aztec/foundation/fields';
import { numToUInt32BE } from '@aztec/foundation/serialize';
Expand Down Expand Up @@ -257,3 +257,57 @@ export function getMessageSentLogs(
toBlock: toBlock + 1n, // the toBlock argument in getLogs is exclusive
});
}

export type SubmitBlockProof = {
header: Header;
archiveRoot: Fr;
proverId: Fr;
aggregationObject: Buffer;
proof: Proof;
};

/**
* Gets block metadata (header and archive snapshot) from the calldata of an L1 transaction.
* Assumes that the block was published from an EOA.
* TODO: Add retries and error management.
* @param publicClient - The viem public client to use for transaction retrieval.
* @param txHash - Hash of the tx that published it.
* @param l2BlockNum - L2 block number.
* @returns L2 block metadata (header and archive) from the calldata, deserialized
*/
export async function getBlockProofFromSubmitProofTx(
publicClient: PublicClient,
txHash: `0x${string}`,
l2BlockNum: bigint,
expectedProverId: Fr,
): Promise<SubmitBlockProof> {
const { input: data } = await publicClient.getTransaction({ hash: txHash });
const { functionName, args } = decodeFunctionData({
abi: RollupAbi,
data,
});

if (!(functionName === 'submitProof')) {
throw new Error(`Unexpected method called ${functionName}`);
}
const [headerHex, archiveHex, proverIdHex, aggregationObjectHex, proofHex] = args!;

const header = Header.fromBuffer(Buffer.from(hexToBytes(headerHex)));
const proverId = Fr.fromString(proverIdHex);

const blockNumberFromHeader = header.globalVariables.blockNumber.toBigInt();
if (blockNumberFromHeader !== l2BlockNum) {
throw new Error(`Block number mismatch: expected ${l2BlockNum} but got ${blockNumberFromHeader}`);
}
if (!proverId.equals(expectedProverId)) {
throw new Error(`Prover ID mismatch: expected ${expectedProverId} but got ${proverId}`);
}

return {
header,
proverId,
aggregationObject: Buffer.from(hexToBytes(aggregationObjectHex)),
archiveRoot: Fr.fromString(archiveHex),
proof: Proof.fromBuffer(Buffer.from(hexToBytes(proofHex))),
};
}
1 change: 1 addition & 0 deletions yarn-project/aztec/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
"@aztec/noir-protocol-circuits-types": "workspace:^",
"@aztec/p2p": "workspace:^",
"@aztec/p2p-bootstrap": "workspace:^",
"@aztec/proof-verifier": "workspace:^",
"@aztec/protocol-contracts": "workspace:^",
"@aztec/prover-client": "workspace:^",
"@aztec/prover-node": "workspace:^",
Expand Down
10 changes: 10 additions & 0 deletions yarn-project/aztec/src/cli/aztec_start_options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import {
isBooleanConfigValue,
} from '@aztec/foundation/config';
import { bootnodeConfigMappings, p2pConfigMappings } from '@aztec/p2p';
import { proofVerifierConfigMappings } from '@aztec/proof-verifier';
import { proverClientConfigMappings } from '@aztec/prover-client';
import { proverNodeConfigMappings } from '@aztec/prover-node';
import { allPxeConfigMappings } from '@aztec/pxe';
Expand Down Expand Up @@ -295,6 +296,15 @@ export const aztecStartOptions: { [key: string]: AztecStartOption[] } = {
},
...getOptions('bot', botConfigMappings),
],
'PROOF VERIFIER': [
{
flag: '--proof-verifier',
description: 'Starts Aztec Proof Verifier with options',
defaultValue: undefined,
envVar: undefined,
},
...getOptions('proofVerifier', proofVerifierConfigMappings),
],
TXE: [
{
flag: '--txe',
Expand Down
26 changes: 26 additions & 0 deletions yarn-project/aztec/src/cli/cmds/start_proof_verifier.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import { type ServerList } from '@aztec/foundation/json-rpc/server';
import { type LogFn } from '@aztec/foundation/log';
import { ProofVerifier, proofVerifierConfigMappings } from '@aztec/proof-verifier';
import { createAndStartTelemetryClient, telemetryClientConfigMappings } from '@aztec/telemetry-client/start';

import { extractRelevantOptions } from '../util.js';

export async function startProofVerifier(
options: any,
signalHandlers: (() => Promise<void>)[],
userLog: LogFn,
): Promise<ServerList> {
const services: ServerList = [];

const config = extractRelevantOptions(options, proofVerifierConfigMappings, 'proofVerifier');

const telemetryConfig = extractRelevantOptions(options, telemetryClientConfigMappings, 'tel');
const telemetry = await createAndStartTelemetryClient(telemetryConfig);
const proofVerifier = await ProofVerifier.new(config, telemetry);

userLog('Starting proof verifier');
proofVerifier.start();

signalHandlers.push(() => proofVerifier.stop());
return services;
}
209 changes: 209 additions & 0 deletions yarn-project/aztec/terraform/proof-verifier/main.tf
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
terraform {
backend "s3" {
bucket = "aztec-terraform"
region = "eu-west-2"
}
required_providers {
aws = {
source = "hashicorp/aws"
version = "3.74.2"
}
}
}

# Define provider and region
provider "aws" {
region = "eu-west-2"
}

data "terraform_remote_state" "aztec2_iac" {
backend = "s3"
config = {
bucket = "aztec-terraform"
key = "aztec2/iac"
region = "eu-west-2"
}
}

data "terraform_remote_state" "setup_iac" {
backend = "s3"
config = {
bucket = "aztec-terraform"
key = "setup/setup-iac"
region = "eu-west-2"
}
}

resource "aws_cloudwatch_log_group" "aztec-proof-verifier-log-group" {
name = "/fargate/service/${var.DEPLOY_TAG}/aztec-proof-verifier"
retention_in_days = 14
}

resource "aws_service_discovery_service" "aztec-proof-verifier" {
name = "${var.DEPLOY_TAG}-aztec-proof-verifier"

health_check_custom_config {
failure_threshold = 1
}

dns_config {
namespace_id = data.terraform_remote_state.setup_iac.outputs.local_service_discovery_id

dns_records {
ttl = 60
type = "A"
}

dns_records {
ttl = 60
type = "SRV"
}

routing_policy = "MULTIVALUE"
}

# Terraform just fails if this resource changes and you have registered instances.
provisioner "local-exec" {
when = destroy
command = "${path.module}/../servicediscovery-drain.sh ${self.id}"
}
}

# Create a fleet.
data "template_file" "user_data" {
template = <<EOF
#!/bin/bash
echo ECS_CLUSTER=${data.terraform_remote_state.setup_iac.outputs.ecs_cluster_name} >> /etc/ecs/ecs.config
echo 'ECS_INSTANCE_ATTRIBUTES={"group": "${var.DEPLOY_TAG}-proof-verifier"}' >> /etc/ecs/ecs.config
EOF
}

resource "aws_launch_template" "proof_verifier_launch_template" {
name = "${var.DEPLOY_TAG}-launch-template"
image_id = "ami-0cd4858f2b923aa6b"
instance_type = "m7a.2xlarge" // 8 cores, 32 GB
vpc_security_group_ids = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id]

iam_instance_profile {
name = data.terraform_remote_state.setup_iac.outputs.ecs_instance_profile_name
}

key_name = data.terraform_remote_state.setup_iac.outputs.ecs_instance_key_pair_name

user_data = base64encode(data.template_file.user_data.rendered)

tag_specifications {
resource_type = "instance"
tags = {
Name = "${var.DEPLOY_TAG}-proof-verifier"
prometheus = ""
}
}
}

resource "aws_ec2_fleet" "proof_verifier_fleet" {
launch_template_config {
launch_template_specification {
launch_template_id = aws_launch_template.proof_verifier_launch_template.id
version = aws_launch_template.proof_verifier_launch_template.latest_version
}

override {
subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id
availability_zone = "eu-west-2a"
max_price = "0.15"
}

override {
subnet_id = data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id
availability_zone = "eu-west-2b"
max_price = "0.15"
}
}

target_capacity_specification {
default_target_capacity_type = "on-demand"
total_target_capacity = 1
spot_target_capacity = 0
on_demand_target_capacity = 1
}

terminate_instances = true
terminate_instances_with_expiration = true
}

resource "aws_ecs_task_definition" "aztec-proof-verifier" {
family = "${var.DEPLOY_TAG}-aztec-proof-verifier"
network_mode = "awsvpc"
requires_compatibilities = ["EC2"]
execution_role_arn = data.terraform_remote_state.setup_iac.outputs.ecs_task_execution_role_arn
task_role_arn = data.terraform_remote_state.aztec2_iac.outputs.cloudwatch_logging_ecs_role_arn

container_definitions = jsonencode([
{
name = "${var.DEPLOY_TAG}-aztec-proof-verifier"
image = "${var.DOCKERHUB_ACCOUNT}/aztec:${var.DEPLOY_TAG}"
command = ["start", "--proof-verifier"]
essential = true
cpu = 8192,
memoryReservation = 32768,
portMappings = []
environment = [
{ name = "PROOF_VERIFIER_L1_START_BLOCK", value = "15918000" },
{ name = "PROOF_VERIFIER_POLL_INTERVAL_MS", value = var.PROOF_VERIFIER_POLL_INTERVAL_MS },
{ name = "ETHEREUM_HOST", value = var.ETHEREUM_HOST },
{ name = "L1_CHAIN_ID", value = var.L1_CHAIN_ID },
{ name = "ROLLUP_CONTRACT_ADDRESS", value = var.ROLLUP_CONTRACT_ADDRESS },
{ name = "LOG_LEVEL", value = var.LOG_LEVEL },
{ name = "NETWORK", value = var.DEPLOY_TAG },
{ name = "LOG_JSON", value = "1" }
]
logConfiguration = {
logDriver = "awslogs"
options = {
"awslogs-group" = aws_cloudwatch_log_group.aztec-proof-verifier-log-group.name
"awslogs-region" = "eu-west-2"
"awslogs-stream-prefix" = "ecs"
}
}
}
])
}

resource "aws_ecs_service" "aztec-proof-verifier" {
name = "${var.DEPLOY_TAG}-aztec-proof-verifier"
cluster = data.terraform_remote_state.setup_iac.outputs.ecs_cluster_id
launch_type = "EC2"
desired_count = 1
deployment_maximum_percent = 100
deployment_minimum_healthy_percent = 0
force_new_deployment = true
enable_execute_command = true

network_configuration {
subnets = [
data.terraform_remote_state.setup_iac.outputs.subnet_az1_private_id,
data.terraform_remote_state.setup_iac.outputs.subnet_az2_private_id
]
security_groups = [data.terraform_remote_state.setup_iac.outputs.security_group_private_id]
}

# load_balancer {
# target_group_arn = aws_alb_target_group.bot_http.arn
# container_name = "${var.DEPLOY_TAG}-aztec-proof-verifier"
# container_port = 80
# }

service_registries {
registry_arn = aws_service_discovery_service.aztec-proof-verifier.arn
container_name = "${var.DEPLOY_TAG}-aztec-proof-verifier"
container_port = 80
}

placement_constraints {
type = "memberOf"
expression = "attribute:group == ${var.DEPLOY_TAG}-proof-verifier"
}

task_definition = aws_ecs_task_definition.aztec-proof-verifier.family
}
Loading