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
1 change: 1 addition & 0 deletions spartan/scripts/test_kind.sh
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ export NAMESPACE="$namespace"
export CONTAINER_PXE_PORT="8081"
export CONTAINER_ETHEREUM_PORT="8545"
export CONTAINER_NODE_PORT="8080"
export CONTAINER_NODE_ADMIN_PORT="8880"
export CONTAINER_SEQUENCER_PORT="8080"
export CONTAINER_PROVER_NODE_PORT="8080"
export CONTAINER_METRICS_PORT="80"
Expand Down
9 changes: 7 additions & 2 deletions yarn-project/aztec-node/src/aztec-node/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,12 @@ import type {
} from '@aztec/stdlib/contract';
import type { GasFees } from '@aztec/stdlib/gas';
import { computePublicDataTreeLeafSlot, siloNullifier } from '@aztec/stdlib/hash';
import type { AztecNode, GetContractClassLogsResponse, GetPublicLogsResponse } from '@aztec/stdlib/interfaces/client';
import type {
AztecNode,
AztecNodeAdmin,
GetContractClassLogsResponse,
GetPublicLogsResponse,
} from '@aztec/stdlib/interfaces/client';
import {
type ClientProtocolCircuitVerifier,
type L2LogsSource,
Expand Down Expand Up @@ -93,7 +98,7 @@ import { NodeMetrics } from './node_metrics.js';
/**
* The aztec node.
*/
export class AztecNodeService implements AztecNode, Traceable {
export class AztecNodeService implements AztecNode, AztecNodeAdmin, Traceable {
private packageVersion: string;
private metrics: NodeMetrics;

Expand Down
16 changes: 15 additions & 1 deletion yarn-project/aztec/src/cli/aztec_start_action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
// list of 'stop' functions to call when process ends
const signalHandlers: Array<() => Promise<void>> = [];
const services: NamespacedApiHandlers = {};
const adminServices: NamespacedApiHandlers = {};
let config: ChainConfig | undefined = undefined;

if (options.sandbox) {
Expand Down Expand Up @@ -55,7 +56,7 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
}
if (options.node) {
const { startNode } = await import('./cmds/start_node.js');
({ config } = await startNode(options, signalHandlers, services, userLog));
({ config } = await startNode(options, signalHandlers, services, adminServices, userLog));
} else if (options.bot) {
const { startBot } = await import('./cmds/start_bot.js');
await startBot(options, signalHandlers, services, userLog);
Expand Down Expand Up @@ -97,6 +98,8 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg

installSignalHandlers(debugLogger.info, signalHandlers);
const versions = getVersions(config);

// Start the main JSON-RPC server
if (Object.entries(services).length > 0) {
const rpcServer = createNamespacedSafeJsonRpcServer(services, {
http200OnError: false,
Expand All @@ -106,4 +109,15 @@ export async function aztecStart(options: any, userLog: LogFn, debugLogger: Logg
const { port } = await startHttpRpcServer(rpcServer, { port: options.port });
debugLogger.info(`Aztec Server listening on port ${port}`, versions);
}

// If there are any admin services, start a separate JSON-RPC server for them
if (Object.entries(adminServices).length > 0) {
const rpcServer = createNamespacedSafeJsonRpcServer(adminServices, {
http200OnError: false,
log: debugLogger,
middlewares: [getOtelJsonRpcPropagationMiddleware(), getVersioningMiddleware(versions)],
});
const { port } = await startHttpRpcServer(rpcServer, { port: options.adminPort });
debugLogger.info(`Aztec Server admin API listening on port ${port}`, versions);
}
}
9 changes: 8 additions & 1 deletion yarn-project/aztec/src/cli/aztec_start_options.ts
Original file line number Diff line number Diff line change
Expand Up @@ -97,11 +97,18 @@ export const aztecStartOptions: { [key: string]: AztecStartOption[] } = {
API: [
{
flag: '--port <value>',
description: 'Port to run the Aztec Services on on',
description: 'Port to run the Aztec Services on',
defaultValue: 8080,
envVar: 'AZTEC_PORT',
parseVal: val => parseInt(val, 10),
},
{
flag: '--admin-port <value>',
description: 'Port to run admin APIs of Aztec Services on on',
defaultValue: 8880,
envVar: 'AZTEC_ADMIN_PORT',
parseVal: val => parseInt(val, 10),
},
{
flag: '--api-prefix <value>',
description: 'Prefix for API routes on any service that is started',
Expand Down
4 changes: 3 additions & 1 deletion yarn-project/aztec/src/cli/cmds/start_node.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import { type AztecNodeConfig, aztecNodeConfigMappings, getConfigEnvVars } from
import { NULL_KEY } from '@aztec/ethereum';
import type { NamespacedApiHandlers } from '@aztec/foundation/json-rpc/server';
import type { LogFn } from '@aztec/foundation/log';
import { AztecNodeApiSchema, type PXE } from '@aztec/stdlib/interfaces/client';
import { AztecNodeAdminApiSchema, AztecNodeApiSchema, type PXE } from '@aztec/stdlib/interfaces/client';
import { P2PApiSchema } from '@aztec/stdlib/interfaces/server';
import {
type TelemetryClientConfig,
Expand All @@ -22,6 +22,7 @@ export async function startNode(
options: any,
signalHandlers: (() => Promise<void>)[],
services: NamespacedApiHandlers,
adminServices: NamespacedApiHandlers,
userLog: LogFn,
): Promise<{ config: AztecNodeConfig }> {
// options specifically namespaced with --node.<option>
Expand Down Expand Up @@ -141,6 +142,7 @@ export async function startNode(
// Add node and p2p to services list
services.node = [node, AztecNodeApiSchema];
services.p2p = [node.getP2P(), P2PApiSchema];
adminServices.nodeAdmin = [node, AztecNodeAdminApiSchema];

// Add node stop function to signal handlers
signalHandlers.push(node.stop.bind(node));
Expand Down
4 changes: 4 additions & 0 deletions yarn-project/aztec/terraform/node/main.tf
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,10 @@ resource "aws_ecs_task_definition" "aztec-node" {
name = "AZTEC_PORT"
value = "80"
},
{
name = "AZTEC_ADMIN_PORT"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unrelated: is this file even used anymore?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Dunno

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No

value = "8880"
},
{
name = "ETHEREUM_HOSTS"
value = "${local.eth_host}"
Expand Down
7 changes: 5 additions & 2 deletions yarn-project/bot/src/bot.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { times } from '@aztec/foundation/collection';
import type { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
import type { TokenContract } from '@aztec/noir-contracts.js/Token';
import { Gas } from '@aztec/stdlib/gas';
import type { AztecNode, PXE } from '@aztec/stdlib/interfaces/client';
import type { AztecNode, AztecNodeAdmin, PXE } from '@aztec/stdlib/interfaces/client';

import type { BotConfig } from './config.js';
import { BotFactory } from './factory.js';
Expand All @@ -31,7 +31,10 @@ export class Bot {
public config: BotConfig,
) {}

static async create(config: BotConfig, dependencies: { pxe?: PXE; node?: AztecNode } = {}): Promise<Bot> {
static async create(
config: BotConfig,
dependencies: { pxe?: PXE; node?: AztecNode; nodeAdmin?: AztecNodeAdmin },
): Promise<Bot> {
const { wallet, token, recipient } = await new BotFactory(config, dependencies).setup();
return new Bot(wallet, token, recipient, config);
}
Expand Down
8 changes: 8 additions & 0 deletions yarn-project/bot/src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ export enum SupportedTokenContracts {
export type BotConfig = {
/** The URL to the Aztec node to check for tx pool status. */
nodeUrl: string | undefined;
/** The URL to the Aztec node admin API to force-flush txs if configured. */
nodeAdminUrl: string | undefined;
/** URL to the PXE for sending txs, or undefined if an in-proc PXE is used. */
pxeUrl: string | undefined;
/** Url of the ethereum host. */
Expand Down Expand Up @@ -74,6 +76,7 @@ export type BotConfig = {
export const BotConfigSchema = z
.object({
nodeUrl: z.string().optional(),
nodeAdminUrl: z.string().optional(),
pxeUrl: z.string().optional(),
l1RpcUrls: z.array(z.string()).optional(),
l1Mnemonic: z.string().optional(),
Expand All @@ -99,6 +102,7 @@ export const BotConfigSchema = z
})
.transform(config => ({
nodeUrl: undefined,
nodeAdminUrl: undefined,
pxeUrl: undefined,
l1RpcUrls: undefined,
l1Mnemonic: undefined,
Expand All @@ -114,6 +118,10 @@ export const botConfigMappings: ConfigMappingsType<BotConfig> = {
env: 'AZTEC_NODE_URL',
description: 'The URL to the Aztec node to check for tx pool status.',
},
nodeAdminUrl: {
env: 'AZTEC_NODE_ADMIN_URL',
description: 'The URL to the Aztec node admin API to force-flush txs if configured.',
},
pxeUrl: {
env: 'BOT_PXE_URL',
description: 'URL to the PXE for sending txs, or undefined if an in-proc PXE is used.',
Expand Down
17 changes: 12 additions & 5 deletions yarn-project/bot/src/factory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { getDeployedTestAccountsWallets, getInitialTestAccounts } from '@aztec/a
import {
type AccountWallet,
AztecAddress,
type AztecNode,
BatchCall,
ContractFunctionInteraction,
type DeployMethod,
Expand All @@ -19,6 +18,7 @@ import { createEthereumChain, createL1Clients } from '@aztec/ethereum';
import { Fr } from '@aztec/foundation/fields';
import { EasyPrivateTokenContract } from '@aztec/noir-contracts.js/EasyPrivateToken';
import { TokenContract } from '@aztec/noir-contracts.js/Token';
import type { AztecNode, AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
import { deriveSigningKey } from '@aztec/stdlib/keys';
import { makeTracedFetch } from '@aztec/telemetry-client';

Expand All @@ -31,11 +31,17 @@ const MIN_BALANCE = 1e3;
export class BotFactory {
private pxe: PXE;
private node?: AztecNode;
private nodeAdmin?: AztecNodeAdmin;
private log = createLogger('bot');

constructor(private readonly config: BotConfig, dependencies: { pxe?: PXE; node?: AztecNode } = {}) {
if (config.flushSetupTransactions && !dependencies.node) {
throw new Error(`Either a node client or node url must be provided if transaction flushing is requested`);
constructor(
private readonly config: BotConfig,
dependencies: { pxe?: PXE; nodeAdmin?: AztecNodeAdmin; node?: AztecNode },
) {
if (config.flushSetupTransactions && !dependencies.nodeAdmin) {
throw new Error(
`Either a node admin client or node admin url must be provided if transaction flushing is requested`,
);
}
if (config.senderPrivateKey && !dependencies.node) {
throw new Error(
Expand All @@ -47,6 +53,7 @@ export class BotFactory {
}

this.node = dependencies.node;
this.nodeAdmin = dependencies.nodeAdmin;

if (dependencies.pxe) {
this.log.info(`Using local PXE`);
Expand Down Expand Up @@ -250,7 +257,7 @@ export class BotFactory {
if (this.config.flushSetupTransactions) {
this.log.verbose('Flushing transactions');
try {
await this.node!.flushTxs();
await this.nodeAdmin!.flushTxs();
} catch (err) {
this.log.error(`Failed to flush transactions: ${err}`);
}
Expand Down
14 changes: 10 additions & 4 deletions yarn-project/bot/src/runner.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type AztecNode, type PXE, createAztecNodeClient, createLogger } from '@aztec/aztec.js';
import { RunningPromise } from '@aztec/foundation/running-promise';
import { type AztecNodeAdmin, createAztecNodeAdminClient } from '@aztec/stdlib/interfaces/client';
import { type TelemetryClient, type Traceable, type Tracer, makeTracedFetch, trackSpan } from '@aztec/telemetry-client';

import { Bot } from './bot.js';
Expand All @@ -11,6 +12,7 @@ export class BotRunner implements BotRunnerApi, Traceable {
private bot?: Promise<Bot>;
private pxe?: PXE;
private node: AztecNode;
private nodeAdmin?: AztecNodeAdmin;
private runningPromise: RunningPromise;
private consecutiveErrors = 0;
private healthy = true;
Expand All @@ -19,15 +21,19 @@ export class BotRunner implements BotRunnerApi, Traceable {

public constructor(
private config: BotConfig,
dependencies: { pxe?: PXE; node?: AztecNode; telemetry: TelemetryClient },
dependencies: { pxe?: PXE; node?: AztecNode; nodeAdmin?: AztecNodeAdmin; telemetry: TelemetryClient },
) {
this.tracer = dependencies.telemetry.getTracer('Bot');
this.pxe = dependencies.pxe;
if (!dependencies.node && !config.nodeUrl) {
throw new Error(`Missing node URL in config or dependencies`);
}
this.node =
dependencies.node ?? createAztecNodeClient(config.nodeUrl!, getVersions(), makeTracedFetch([1, 2, 3], true));
const versions = getVersions();
const fetch = makeTracedFetch([1, 2, 3], true);
this.node = dependencies.node ?? createAztecNodeClient(config.nodeUrl!, versions, fetch);
this.nodeAdmin =
dependencies.nodeAdmin ??
(config.nodeAdminUrl ? createAztecNodeAdminClient(config.nodeAdminUrl, versions, fetch) : undefined);
this.runningPromise = new RunningPromise(() => this.#work(), this.log, config.txIntervalSeconds * 1000);
}

Expand Down Expand Up @@ -131,7 +137,7 @@ export class BotRunner implements BotRunnerApi, Traceable {

async #createBot() {
try {
this.bot = Bot.create(this.config, { pxe: this.pxe, node: this.node });
this.bot = Bot.create(this.config, { pxe: this.pxe, node: this.node, nodeAdmin: this.nodeAdmin });
await this.bot;
} catch (err) {
this.log.error(`Error setting up bot: ${err}`);
Expand Down
21 changes: 13 additions & 8 deletions yarn-project/end-to-end/src/e2e_block_building.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ import {
type PublicTxResult,
PublicTxSimulator,
} from '@aztec/simulator/server';
import type { AztecNodeAdmin } from '@aztec/stdlib/interfaces/client';
import type { Tx } from '@aztec/stdlib/tx';
import type { TelemetryClient } from '@aztec/telemetry-client';

Expand All @@ -52,6 +53,7 @@ describe('e2e_block_building', () => {
let owner: Wallet;
let minter: Wallet;
let aztecNode: AztecNode;
let aztecNodeAdmin: AztecNodeAdmin;
let sequencer: TestSequencerClient;
let dateProvider: TestDateProvider | undefined;
let cheatCodes: CheatCodes;
Expand All @@ -69,11 +71,13 @@ describe('e2e_block_building', () => {

beforeAll(async () => {
let sequencerClient: SequencerClient | undefined;
let maybeAztecNodeAdmin: AztecNodeAdmin | undefined;
({
teardown,
pxe,
logger,
aztecNode,
aztecNodeAdmin: maybeAztecNodeAdmin,
wallets: [owner, minter],
sequencer: sequencerClient,
dateProvider,
Expand All @@ -85,16 +89,17 @@ describe('e2e_block_building', () => {
blockCheckIntervalMS: 200,
}));
sequencer = sequencerClient! as TestSequencerClient;
aztecNodeAdmin = maybeAztecNodeAdmin!;
});

afterEach(() => aztecNode.setConfig({ minTxsPerBlock: 1 }));
afterEach(() => aztecNodeAdmin.setConfig({ minTxsPerBlock: 1 }));
afterAll(() => teardown());

it('assembles a block with multiple txs', async () => {
// Assemble N contract deployment txs
// We need to create them sequentially since we cannot have parallel calls to a circuit
const TX_COUNT = 8;
await aztecNode.setConfig({ minTxsPerBlock: TX_COUNT });
await aztecNodeAdmin.setConfig({ minTxsPerBlock: TX_COUNT });
const deployer = new ContractDeployer(artifact, owner);

const ownerAddress = owner.getCompleteAddress().address;
Expand Down Expand Up @@ -140,7 +145,7 @@ describe('e2e_block_building', () => {
// Assemble N contract deployment txs
// We need to create them sequentially since we cannot have parallel calls to a circuit
const TX_COUNT = 4;
await aztecNode.setConfig({ minTxsPerBlock: TX_COUNT });
await aztecNodeAdmin.setConfig({ minTxsPerBlock: TX_COUNT });

const methods = times(TX_COUNT, i => contract.methods.increment_public_value(ownerAddress, i));
const provenTxs = [];
Expand Down Expand Up @@ -168,7 +173,7 @@ describe('e2e_block_building', () => {
const contract = await StatefulTestContract.deploy(owner, ownerAddress, ownerAddress, 1).send().deployed();
const another = await TestContract.deploy(owner).send().deployed();

await aztecNode.setConfig({ minTxsPerBlock: 16, maxTxsPerBlock: 16 });
await aztecNodeAdmin.setConfig({ minTxsPerBlock: 16, maxTxsPerBlock: 16 });

// Flood nullifiers to grow the size of the nullifier tree.
// Can probably do this more efficiently by batching multiple emit_nullifier calls
Expand All @@ -181,7 +186,7 @@ describe('e2e_block_building', () => {
await Promise.all(sentNullifierTxs.map(tx => tx.wait({ timeout: 600 })));
logger.info(`Nullifier txs sent`);

await aztecNode.setConfig({ minTxsPerBlock: 4, maxTxsPerBlock: 4 });
await aztecNodeAdmin.setConfig({ minTxsPerBlock: 4, maxTxsPerBlock: 4 });

// Now send public functions
const TX_COUNT = 128;
Expand All @@ -207,7 +212,7 @@ describe('e2e_block_building', () => {
// We also set enforceTimetable so the deadline makes sense, otherwise we may be starting the
// block too late into the slot, and start processing when the deadline has already passed.
logger.info(`Updating aztec node config`);
await aztecNode.setConfig({ minTxsPerBlock: 1, maxTxsPerBlock: TX_COUNT, enforceTimeTable: true });
await aztecNodeAdmin.setConfig({ minTxsPerBlock: 1, maxTxsPerBlock: TX_COUNT, enforceTimeTable: true });

// We tweak the sequencer so it uses a fake simulator that adds a delay to every public tx.
const archiver = (aztecNode as AztecNodeService).getContractDataSource();
Expand Down Expand Up @@ -245,7 +250,7 @@ describe('e2e_block_building', () => {

it.skip('can call public function from different tx in same block as deployed', async () => {
// Ensure both txs will land on the same block
await aztecNode.setConfig({ minTxsPerBlock: 2 });
await aztecNodeAdmin.setConfig({ minTxsPerBlock: 2 });

// Deploy a contract in the first transaction
// In the same block, call a public method on the contract
Expand Down Expand Up @@ -493,7 +498,7 @@ describe('e2e_block_building', () => {
.deployed();

logger.info('Updating txs per block to 4');
await aztecNode.setConfig({ minTxsPerBlock: 4, maxTxsPerBlock: 4 });
await aztecNodeAdmin.setConfig({ minTxsPerBlock: 4, maxTxsPerBlock: 4 });

logger.info('Spamming the network with public txs');
const txs = [];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ describe('e2e_deploy_contract deploy method', () => {
}, 300_000);

it('publicly deploys a contract in one tx and calls a public function on it later in the same block', async () => {
await t.aztecNode.setConfig({ minTxsPerBlock: 2 });
await t.aztecNodeAdmin.setConfig({ minTxsPerBlock: 2 });

const owner = wallet.getAddress();
logger.debug('Initializing deploy method');
Expand Down
Loading