Skip to content

Commit d979a26

Browse files
authored
refactor: move registerContractFunctionSignatures to the node debug API (#24066)
Fixes A-1220 ## Why `node.registerContractFunctionSignatures` was an always-on, unauthenticated write on the main `AztecNode` JSON-RPC surface. It populates a per-node, in-memory, non-gossiped selector→name map used only to name public-execution stack traces, so it has no business on a prod node's public API (anyone can spam it up to the cap, and you'd have to keep talking to the same node for it to mean anything). Decoding traces should be a client concern. ## What Relocate the method from the always-on `AztecNode` interface to the existing, gated `AztecNodeDebug` interface (served under the `nodeDebug_` namespace, only mounted when the node runs with debug endpoints enabled — always on in the in-process sandbox, off by default on standalone nodes). The node-side read path (`getDebugFunctionName` → AVM trace naming) is unchanged; only the RPC write moves. The PXE now calls it through an **optional** `nodeDebug` client and skips registration entirely when the node does not expose the debug API. PXE-side simulation errors keep named traces regardless, via the existing ABI-based enrichment in `pxe/src/error_enriching.ts`. - **stdlib**: removed `registerContractFunctionSignatures` from `AztecNode` + `AztecNodeApiSchema`; added it (and the length/count caps) to `AztecNodeDebug` + `AztecNodeDebugApiSchema`. - **aztec-node**: server impl unchanged — `AztecNodeService` already implements `AztecNodeDebug`, so the method now satisfies that interface and is served under `nodeDebug_`. - **pxe**: optional `nodeDebug?: AztecNodeDebug` on `PXECreateArgs`/constructor; both registration call sites become `this.nodeDebug?.registerContractFunctionSignatures(...)`. Threaded `options.nodeDebug` through all three `createPXE` entrypoints (option A — explicit injection). - **e2e**: wired `nodeDebug` in `end-to-end/src/fixtures/setup.ts` for both PXE-creation paths — `setup()` passes the in-process node service directly; `setupPXEAndGetWallet()` passes it via an `isAztecNodeDebug` type guard (one caller types its node loosely). - **tests**: moved the schema round-trip case from the node interface test to the debug interface test; retargeted the PXE registration tests to the `nodeDebug` mock; updated the `node_rpc_perf` benchmark. - **docs**: dropped the moved method from the generated node API reference (the generator only documents `node_`/`nodeAdmin_`), and added a migration note. ## Breaking change `node_registerContractFunctionSignatures` is removed from the main node RPC. Callers must use `nodeDebug_registerContractFunctionSignatures` against a debug-enabled node. See the migration note. ## Verification Local build could not be run here: the workspace is a cold checkout (noir submodule packages absent, no Rust/Docker), so `yarn install`/`yarn build` cannot bootstrap. The change is a contained TypeScript interface relocation + optional-client wiring; relying on CI for the full build/lint/test. A follow-up could wire `createAztecNodeDebugClient(nodeUrl)` into the URL-based PXE creators (bot/embedded wallet) if named traces are wanted against a debug-enabled remote node. --- *Created by [claudebox](https://claudebox.work/v2/sessions/b8d3c4fab6c0225a) · group: `slackbot`*
1 parent 96d47a0 commit d979a26

17 files changed

Lines changed: 78 additions & 39 deletions

File tree

docs/docs-developers/docs/resources/migration_notes.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ All Aztec node JSON-RPC method prefixes have changed:
9393
If you call the node RPC directly (e.g. via `curl` or a custom client), update all method names accordingly.
9494
Clients created via `createAztecNodeClient`, `createAztecNodeAdminClient`, and `createAztecNodeDebugClient` are updated automatically.
9595

96+
### [Node RPC] `registerContractFunctionSignatures` moved to the debug API
97+
98+
`registerContractFunctionSignatures` is no longer part of the main node JSON-RPC API (`aztec_` namespace). It is now a debug-only method exposed under the `aztecDebug_` namespace, which is only mounted when the node runs with debug endpoints enabled (`--node-debug`, always on in the in-process sandbox). This removes an unauthenticated write to node memory from prod-like nodes.
99+
100+
Clients that registered public function signatures over `aztec_registerContractFunctionSignatures` should call `aztecDebug_registerContractFunctionSignatures` against a debug-enabled node instead. In the PXE, this is now driven by an optional debug client: pass a `nodeDebug` client (e.g. `createAztecNodeDebugClient(nodeUrl)`) when creating the PXE to keep named public-execution traces; when it is absent, signature registration is skipped. Client-side error enrichment from the contract ABI is unaffected.
101+
96102
### [Aztec.nr] `get_pending_tagged_logs` oracle interface updated (oracle version 28)
97103

98104
The `aztec_utl_getPendingTaggedLogs` oracle now takes an additional `provided_secrets` parameter of type `EphemeralArray<ProvidedSecret>`. This lets apps pass tagging secrets that PXE cannot derive on its own (e.g. handshake-derived secrets) alongside the secrets PXE manages internally.

docs/scripts/node_api_reference_generation/generate_node_api_reference.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -606,7 +606,7 @@ const METHOD_GROUPS: { heading: string; namespace: string; methods: string[] }[]
606606
{
607607
heading: 'Debug operations',
608608
namespace: 'aztec',
609-
methods: ['registerContractFunctionSignatures', 'getAllowedPublicSetup'],
609+
methods: ['getAllowedPublicSetup'],
610610
},
611611
{
612612
heading: 'Admin API',

yarn-project/end-to-end/src/bench/node_rpc_perf.test.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ import { BlockNumber, EpochNumber } from '@aztec/foundation/branded-types';
1515
import { Timer } from '@aztec/foundation/timer';
1616
import { TokenContract } from '@aztec/noir-contracts.js/Token';
1717
import { BlockHash } from '@aztec/stdlib/block';
18+
import type { AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
1819
import { SiloedTag, Tag } from '@aztec/stdlib/logs';
1920
import { MerkleTreeId } from '@aztec/stdlib/trees';
2021
import type { Tx, TxHash } from '@aztec/stdlib/tx';
@@ -98,7 +99,7 @@ describe('e2e_node_rpc_perf', () => {
9899
jest.setTimeout(10 * 60 * 1000); // 10 minutes
99100

100101
let logger: Logger;
101-
let aztecNode: AztecNode;
102+
let aztecNode: AztecNode & AztecNodeDebug;
102103
let wallet: TestWallet;
103104
let ownerAddress: AztecAddress;
104105
let rollupCheatCodes: RollupCheatCodes;

yarn-project/end-to-end/src/e2e_2_pxes.test.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { Logger } from '@aztec/aztec.js/log';
66
import type { AztecNode } from '@aztec/aztec.js/node';
77
import { TokenContract } from '@aztec/noir-contracts.js/Token';
88
import { ChildContract } from '@aztec/noir-test-contracts.js/Child';
9+
import type { AztecNodeDebug } from '@aztec/stdlib/interfaces/client';
910

1011
import { expect, jest } from '@jest/globals';
1112

@@ -19,7 +20,7 @@ const TIMEOUT = 300_000;
1920
describe('e2e_2_pxes', () => {
2021
jest.setTimeout(TIMEOUT);
2122

22-
let aztecNode: AztecNode;
23+
let aztecNode: AztecNode & AztecNodeDebug;
2324
let walletA: TestWallet;
2425
let walletB: TestWallet;
2526
let accountAAddress: AztecAddress;
@@ -30,12 +31,12 @@ describe('e2e_2_pxes', () => {
3031
let teardownB: () => Promise<void>;
3132

3233
async function setupSecondaryPXE(
33-
node: AztecNode,
34+
node: AztecNode & AztecNodeDebug,
3435
fundedAccounts: InitialAccountData[],
3536
accountIndex: number,
3637
pxeName: string,
3738
) {
38-
const { wallet, teardown } = await setupPXEAndGetWallet(node, {}, undefined, pxeName);
39+
const { wallet, teardown } = await setupPXEAndGetWallet(node, node, {}, undefined, pxeName);
3940
const accountManager = await wallet.createSchnorrAccount(
4041
fundedAccounts[accountIndex].secret,
4142
fundedAccounts[accountIndex].salt,

yarn-project/end-to-end/src/e2e_synching.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -559,7 +559,7 @@ describe('e2e_synching', () => {
559559
const aztecNode = await AztecNodeService.createAndSync(opts.config!, {}, { genesis: opts.genesis });
560560
const sequencer = aztecNode.getSequencer();
561561

562-
const { wallet } = await setupPXEAndGetWallet(aztecNode!);
562+
const { wallet } = await setupPXEAndGetWallet(aztecNode!, aztecNode!);
563563
variant.setWallet(wallet);
564564
const defaultAccountAddress = (await variant.deployAccounts(opts.initialFundedAccounts!.slice(0, 1)))[0];
565565

@@ -700,7 +700,7 @@ describe('e2e_synching', () => {
700700
expect(await aztecNode.getBlockNumber()).toBeLessThan(blockBeforePrune);
701701

702702
// We need to start the pxe after the re-org for now, because it won't handle it otherwise
703-
const { wallet } = await setupPXEAndGetWallet(aztecNode!);
703+
const { wallet } = await setupPXEAndGetWallet(aztecNode!, aztecNode!);
704704
variant.setWallet(wallet);
705705

706706
const blockBefore = await aztecNode.getBlock(await aztecNode.getBlockNumber());
@@ -751,7 +751,7 @@ describe('e2e_synching', () => {
751751
const aztecNode = await AztecNodeService.createAndSync(opts.config!, {}, { genesis: opts.genesis });
752752
const sequencer = aztecNode.getSequencer();
753753

754-
const { wallet: newWallet } = await setupPXEAndGetWallet(aztecNode!);
754+
const { wallet: newWallet } = await setupPXEAndGetWallet(aztecNode!, aztecNode!);
755755
variant.setWallet(newWallet);
756756

757757
const blockBefore = await aztecNode.getBlock(await aztecNode.getBlockNumber());

yarn-project/end-to-end/src/fixtures/e2e_prover_test.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,7 @@ export class FullProverTest {
186186
this.logger.verbose(`Main setup completed, initializing full prover PXE, Node, and Prover Node`);
187187
const { wallet: provenWallet, teardown: provenTeardown } = await setupPXEAndGetWallet(
188188
this.aztecNode,
189+
this.context.aztecNode,
189190
{ proverEnabled: this.realProofs },
190191
undefined,
191192
'pxe-proven',

yarn-project/end-to-end/src/fixtures/setup.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -119,13 +119,16 @@ export async function setupSharedBlobStorage(config: { dataDirectory?: string }
119119
/**
120120
* Sets up Private eXecution Environment (PXE) and returns the corresponding test wallet.
121121
* @param aztecNode - An instance of Aztec Node.
122+
* @param nodeDebug - The node's debug API, used to register public function signatures for named traces; pass
123+
* `undefined` when the node does not expose it.
122124
* @param opts - Partial configuration for the PXE.
123125
* @param logger - The logger to be used.
124126
* @param actor - Actor label to include in log output (e.g., 'pxe-test').
125127
* @returns A test wallet, logger and teardown function.
126128
*/
127129
export async function setupPXEAndGetWallet(
128130
aztecNode: AztecNode,
131+
nodeDebug: AztecNodeDebug | undefined,
129132
opts: Partial<PXEConfig> = {},
130133
logger = getLogger(),
131134
actor?: string,
@@ -146,7 +149,10 @@ export async function setupPXEAndGetWallet(
146149

147150
const teardown = configuredDataDirectory ? () => Promise.resolve() : () => tryRmDir(PXEConfig.dataDirectory!);
148151

149-
const wallet = await TestWallet.create(aztecNode, PXEConfig, { loggerActorLabel: actor });
152+
const wallet = await TestWallet.create(aztecNode, PXEConfig, {
153+
loggerActorLabel: actor,
154+
nodeDebug,
155+
});
150156

151157
return {
152158
wallet,
@@ -609,6 +615,8 @@ export async function setup(
609615
pxeConfig.proverEnabled = !!pxeOpts.proverEnabled;
610616
const wallet = await TestWallet.create(aztecNodeService, pxeConfig, {
611617
loggerActorLabel: 'pxe-0',
618+
// In-process node implements the debug API, so register public function signatures for named traces.
619+
nodeDebug: aztecNodeService,
612620
...opts.pxeCreationOptions,
613621
});
614622

yarn-project/pxe/src/entrypoints/client/bundle/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export async function createPXE(
6363
const pxeLogger = loggers.pxe ?? createLogger('pxe:service', { actor });
6464
const pxe = await PXE.create({
6565
node: aztecNode,
66+
nodeDebug: options.nodeDebug,
6667
store,
6768
proofCreator: prover,
6869
simulator,

yarn-project/pxe/src/entrypoints/client/lazy/utils.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@ export async function createPXE(
6363
const pxeLogger = loggers.pxe ?? createLogger('pxe:service', { actor });
6464
const pxe = await PXE.create({
6565
node: aztecNode,
66+
nodeDebug: options.nodeDebug,
6667
store,
6768
proofCreator: prover,
6869
simulator,

yarn-project/pxe/src/entrypoints/pxe_creation_options.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import type { BBPrivateKernelProverOptions } from '@aztec/bb-prover/client';
22
import type { Logger } from '@aztec/foundation/log';
33
import type { AztecAsyncKVStore } from '@aztec/kv-store';
44
import type { CircuitSimulator } from '@aztec/simulator/client';
5-
import type { PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
5+
import type { AztecNodeDebug, PrivateKernelProver } from '@aztec/stdlib/interfaces/client';
66

77
import type { ExecutionHooks } from '../hooks/index.js';
88
import type { PreloadedContractsProvider } from '../pxe.js';
@@ -18,6 +18,12 @@ export type PXECreationOptions = {
1818
hooks?: ExecutionHooks;
1919
/** Contracts to preload on startup. Replaces the default when set. */
2020
preloadedContractsProvider?: PreloadedContractsProvider;
21+
/**
22+
* Optional debug API client for the same node. When provided, public function signatures are registered so the
23+
* node can produce named public-execution stack traces. Only available on nodes started with debug endpoints
24+
* enabled; omitted in prod-like setups.
25+
*/
26+
nodeDebug?: AztecNodeDebug;
2127
};
2228

2329
/** Checks if the given value implements the PrivateKernelProver interface via duck-typing. */

0 commit comments

Comments
 (0)