From b2f11596e5c79be0c11ad298e734885e9657e640 Mon Sep 17 00:00:00 2001 From: Gregorio Juliana Date: Thu, 12 Dec 2024 17:01:04 +0100 Subject: [PATCH] feat: PXE sync on demand (#10613) Closes: https://github.com/AztecProtocol/aztec-packages/issues/10296 Removed the running promise of the synchronizer, in favor of manually triggering syncs. Right now, this happens before simulation (tx and unconstrained) The concept of synchronizer is kept, since we still have to contact the node and perform some cleanups in case of a reorg. Should deflake `e2e_2_pxes` and finally means the end of PXE as a framework, in favor of more library-like approach. --- aztec-up/bin/docker-compose.sandbox.yml | 1 - boxes/boxes/vite/src/config.ts | 25 +- boxes/docker-compose.yml | 1 - .../sandbox_reference/sandbox-reference.md | 2 - spartan/aztec-network/templates/pxe.yaml | 4 +- .../aztec.js/src/contract/sent_tx.test.ts | 14 -- yarn-project/aztec.js/src/contract/sent_tx.ts | 17 +- yarn-project/aztec.js/src/index.ts | 1 - .../aztec.js/src/wallet/base_wallet.ts | 7 - yarn-project/aztec/docker-compose.yml | 1 - yarn-project/aztec/src/cli/cmds/start_pxe.ts | 3 - yarn-project/aztec/src/sandbox.ts | 1 - yarn-project/bot/src/factory.ts | 11 - .../circuit-types/src/interfaces/index.ts | 1 - .../circuit-types/src/interfaces/pxe.test.ts | 19 -- .../circuit-types/src/interfaces/pxe.ts | 19 -- .../src/interfaces/sync-status.ts | 13 - yarn-project/cli-wallet/src/bin/index.ts | 6 - yarn-project/cli/src/cmds/pxe/get_block.ts | 23 +- yarn-project/cli/src/cmds/pxe/index.ts | 3 +- .../scripts/docker-compose-no-sandbox.yml | 1 - .../scripts/docker-compose-wallet.yml | 1 - .../end-to-end/scripts/docker-compose.yml | 1 - .../benchmarks/bench_process_history.test.ts | 7 +- .../src/benchmarks/bench_prover.test.ts | 3 - .../benchmarks/bench_publish_rollup.test.ts | 7 +- .../end-to-end/src/benchmarks/utils.ts | 7 +- .../end-to-end/src/e2e_2_pxes.test.ts | 15 +- .../end-to-end/src/e2e_block_building.test.ts | 8 - .../src/fixtures/snapshot_manager.ts | 1 - yarn-project/end-to-end/src/fixtures/utils.ts | 9 +- yarn-project/foundation/src/config/env_var.ts | 1 - yarn-project/pxe/src/bin/index.ts | 5 +- yarn-project/pxe/src/config/index.ts | 7 - .../pxe/src/database/kv_pxe_database.ts | 10 - yarn-project/pxe/src/database/pxe_database.ts | 13 - yarn-project/pxe/src/index.ts | 2 +- .../pxe/src/pxe_service/pxe_service.ts | 235 +++++++----------- .../src/pxe_service/test/pxe_service.test.ts | 2 - .../src/pxe_service/test/pxe_test_suite.ts | 3 - .../pxe/src/simulator_oracle/index.ts | 2 +- .../pxe/src/synchronizer/synchronizer.ts | 76 +----- .../create_pxe_service.ts | 8 +- yarn-project/pxe/src/utils/index.ts | 67 ----- 44 files changed, 145 insertions(+), 518 deletions(-) delete mode 100644 yarn-project/circuit-types/src/interfaces/sync-status.ts rename yarn-project/pxe/src/{pxe_service => utils}/create_pxe_service.ts (93%) delete mode 100644 yarn-project/pxe/src/utils/index.ts diff --git a/aztec-up/bin/docker-compose.sandbox.yml b/aztec-up/bin/docker-compose.sandbox.yml index 186ba3dec69..999aa567685 100644 --- a/aztec-up/bin/docker-compose.sandbox.yml +++ b/aztec-up/bin/docker-compose.sandbox.yml @@ -28,7 +28,6 @@ services: P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 WS_BLOCK_CHECK_INTERVAL_MS: 50 - PXE_BLOCK_POLLING_INTERVAL_MS: 50 ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 PXE_PORT: ${PXE_PORT:-8080} PORT: ${AZTEC_NODE_PORT:-8080} diff --git a/boxes/boxes/vite/src/config.ts b/boxes/boxes/vite/src/config.ts index e17120a3fc5..bced26cc094 100644 --- a/boxes/boxes/vite/src/config.ts +++ b/boxes/boxes/vite/src/config.ts @@ -24,7 +24,10 @@ export class PrivateEnv { accountContract; account: AccountManager; - constructor(private secretKey: Fr, private nodeURL: string) {} + constructor( + private secretKey: Fr, + private nodeURL: string, + ) {} async init() { const config = getPXEServiceConfig(); @@ -33,20 +36,20 @@ export class PrivateEnv { const proofCreator = new TestPrivateKernelProver(); this.pxe = await this.createPXEService(aztecNode, config, proofCreator); const encryptionPrivateKey = deriveMasterIncomingViewingSecretKey( - this.secretKey + this.secretKey, ); this.accountContract = new SingleKeyAccountContract(encryptionPrivateKey); this.account = new AccountManager( this.pxe, this.secretKey, - this.accountContract + this.accountContract, ); } async createPXEService( aztecNode: AztecNode, config: PXEServiceConfig, - proofCreator?: PrivateKernelProver + proofCreator?: PrivateKernelProver, ) { const l1Contracts = await aztecNode.getL1ContractAddresses(); const configWithContracts = { @@ -57,7 +60,7 @@ export class PrivateEnv { const store = await createStore( "pxe_data", configWithContracts, - createLogger("pxe:data:indexeddb") + createLogger("pxe:data:indexeddb"), ); const keyStore = new KeyStore(store); @@ -65,16 +68,16 @@ export class PrivateEnv { const db = await KVPxeDatabase.create(store); const tips = new L2TipsStore(store, "pxe"); - const server = new PXEService( + const pxe = new PXEService( keyStore, aztecNode, db, tips, proofCreator, - config + config, ); - await server.start(); - return server; + await pxe.init(); + return pxe; } async getWallet() { @@ -85,7 +88,7 @@ export class PrivateEnv { export const deployerEnv = new PrivateEnv( SECRET_KEY, - process.env.PXE_URL || "http://localhost:8080" + process.env.PXE_URL || "http://localhost:8080", ); const IGNORE_FUNCTIONS = [ @@ -94,5 +97,5 @@ const IGNORE_FUNCTIONS = [ "sync_notes", ]; export const filteredInterface = BoxReactContractArtifact.functions.filter( - (f) => !IGNORE_FUNCTIONS.includes(f.name) + (f) => !IGNORE_FUNCTIONS.includes(f.name), ); diff --git a/boxes/docker-compose.yml b/boxes/docker-compose.yml index b06cca7ebc8..a19c72fbc17 100644 --- a/boxes/docker-compose.yml +++ b/boxes/docker-compose.yml @@ -17,7 +17,6 @@ services: P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 WS_BLOCK_CHECK_INTERVAL_MS: 50 - PXE_BLOCK_POLLING_INTERVAL_MS: 50 ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 depends_on: - ethereum diff --git a/docs/docs/reference/developer_references/sandbox_reference/sandbox-reference.md b/docs/docs/reference/developer_references/sandbox_reference/sandbox-reference.md index ce0f32341b5..d00ef025751 100644 --- a/docs/docs/reference/developer_references/sandbox_reference/sandbox-reference.md +++ b/docs/docs/reference/developer_references/sandbox_reference/sandbox-reference.md @@ -37,7 +37,6 @@ ARCHIVER_POLLING_INTERVAL_MS=50 P2P_BLOCK_CHECK_INTERVAL_MS=50 SEQ_TX_POLLING_INTERVAL_MS=50 WS_BLOCK_CHECK_INTERVAL_MS=50 -PXE_BLOCK_POLLING_INTERVAL_MS=50 ARCHIVER_VIEM_POLLING_INTERVAL_MS=500 ``` @@ -90,7 +89,6 @@ Variables like `TEST_ACCOUNTS` & `PXE_PORT` are valid here as described above. AZTEC_NODE_URL='http://localhost:8079' # The address of an Aztec Node URL that the PXE will connect to (default: http://localhost:8079) PXE_PORT=8080 # The port that the PXE will be listening to (default: 8080) TEST_ACCOUNTS='true' # Option to deploy 3 test account when sandbox starts. (default: true) -PXE_BLOCK_POLLING_INTERVAL_MS=50 # Interval to check for new L2 blocks. (default: 50) PXE_L2_STARTING_BLOCK=1 # L2 Block to start synching the PXE from (default: 1) ``` diff --git a/spartan/aztec-network/templates/pxe.yaml b/spartan/aztec-network/templates/pxe.yaml index b4ba7d10c12..e91bbd2a10a 100644 --- a/spartan/aztec-network/templates/pxe.yaml +++ b/spartan/aztec-network/templates/pxe.yaml @@ -108,8 +108,8 @@ spec: - -c - | curl -s -X POST -H 'content-type: application/json' \ - -d '{"jsonrpc":"2.0","method":"pxe_isGlobalStateSynchronized","params":[],"id":67}' \ - 127.0.0.1:{{ .Values.pxe.service.nodePort }} | grep -q '"result":true' + -d '{"jsonrpc":"2.0","method":"pxe_getNodeInfo","params":[],"id":67}' \ + 127.0.0.1:{{ .Values.pxe.service.nodePort }} | grep -q '"protocolVersion":1' initialDelaySeconds: {{ .Values.pxe.readinessProbe.initialDelaySeconds }} periodSeconds: {{ .Values.pxe.readinessProbe.periodSeconds }} timeoutSeconds: {{ .Values.pxe.readinessProbe.timeoutSeconds }} diff --git a/yarn-project/aztec.js/src/contract/sent_tx.test.ts b/yarn-project/aztec.js/src/contract/sent_tx.test.ts index c2bf65adb6a..c0f7daf8a57 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.test.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.test.ts @@ -23,22 +23,8 @@ describe('SentTx', () => { pxe.getTxReceipt.mockResolvedValue(txReceipt); }); - it('waits for all notes of the accounts to be available', async () => { - pxe.getSyncStatus.mockResolvedValueOnce({ blocks: 25 }).mockResolvedValueOnce({ blocks: 25 }); - - const actual = await sentTx.wait({ timeout: 1, interval: 0.4 }); - expect(actual).toEqual(txReceipt); - }); - - it('does not wait for notes sync', async () => { - pxe.getSyncStatus.mockResolvedValue({ blocks: 19 }); - const actual = await sentTx.wait({ timeout: 1, interval: 0.4, waitForNotesAvailable: false }); - expect(actual).toEqual(txReceipt); - }); - it('throws if tx is dropped', async () => { pxe.getTxReceipt.mockResolvedValue({ ...txReceipt, status: TxStatus.DROPPED } as TxReceipt); - pxe.getSyncStatus.mockResolvedValue({ blocks: 19 }); await expect(sentTx.wait({ timeout: 1, interval: 0.4, ignoreDroppedReceiptsFor: 0 })).rejects.toThrow(/dropped/); }); diff --git a/yarn-project/aztec.js/src/contract/sent_tx.ts b/yarn-project/aztec.js/src/contract/sent_tx.ts index b7803975b16..99c4eec8650 100644 --- a/yarn-project/aztec.js/src/contract/sent_tx.ts +++ b/yarn-project/aztec.js/src/contract/sent_tx.ts @@ -14,11 +14,6 @@ export type WaitOpts = { interval?: number; /** Whether to wait for the tx to be proven. */ proven?: boolean; - /** - * Whether to wait for the node to notify that the block in which this tx was mined is available to fetch notes from. - * If false, then any queries that depend on state set by this transaction may return stale data. Defaults to true. - **/ - waitForNotesAvailable?: boolean; /** Whether to include information useful for debugging/testing in the receipt. */ debug?: boolean; /** Whether to accept a revert as a status code for the tx when waiting for it. If false, will throw if the tx reverts. */ @@ -31,7 +26,6 @@ export const DefaultWaitOpts: WaitOpts = { provenTimeout: 600, interval: 1, debug: false, - waitForNotesAvailable: true, }; /** @@ -124,16 +118,7 @@ export class SentTx { } return undefined; } - // If we don't care about waiting for notes to be synced, return the receipt - const waitForNotesAvailable = opts?.waitForNotesAvailable ?? DefaultWaitOpts.waitForNotesAvailable; - if (!waitForNotesAvailable) { - return txReceipt; - } - // Check if all sync blocks on the PXE Service are greater or equal than the block in which the tx was mined - const { blocks } = await this.pxe.getSyncStatus(); - const targetBlock = txReceipt.blockNumber!; - const areNotesAvailable = blocks >= targetBlock; - return areNotesAvailable ? txReceipt : undefined; + return txReceipt; }, 'isMined', opts?.timeout ?? DefaultWaitOpts.timeout, diff --git a/yarn-project/aztec.js/src/index.ts b/yarn-project/aztec.js/src/index.ts index 4c42ac375de..c4a15950273 100644 --- a/yarn-project/aztec.js/src/index.ts +++ b/yarn-project/aztec.js/src/index.ts @@ -149,7 +149,6 @@ export { type PXE, type PartialAddress, type PublicKey, - type SyncStatus, } from '@aztec/circuit-types'; // TODO: These kinds of things have no place on our public api. diff --git a/yarn-project/aztec.js/src/wallet/base_wallet.ts b/yarn-project/aztec.js/src/wallet/base_wallet.ts index 35694b490f5..e455ee4c0be 100644 --- a/yarn-project/aztec.js/src/wallet/base_wallet.ts +++ b/yarn-project/aztec.js/src/wallet/base_wallet.ts @@ -10,7 +10,6 @@ import { type PXEInfo, type PrivateExecutionResult, type SiblingPath, - type SyncStatus, type Tx, type TxExecutionRequest, type TxHash, @@ -170,12 +169,6 @@ export abstract class BaseWallet implements Wallet { getNodeInfo(): Promise { return this.pxe.getNodeInfo(); } - isGlobalStateSynchronized() { - return this.pxe.isGlobalStateSynchronized(); - } - getSyncStatus(): Promise { - return this.pxe.getSyncStatus(); - } addAuthWitness(authWitness: AuthWitness) { return this.pxe.addAuthWitness(authWitness); } diff --git a/yarn-project/aztec/docker-compose.yml b/yarn-project/aztec/docker-compose.yml index 3fe35cd42f8..7d158f93f30 100644 --- a/yarn-project/aztec/docker-compose.yml +++ b/yarn-project/aztec/docker-compose.yml @@ -29,7 +29,6 @@ services: P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 WS_BLOCK_CHECK_INTERVAL_MS: 50 - PXE_BLOCK_POLLING_INTERVAL_MS: 50 ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 volumes: - ./log:/usr/src/yarn-project/aztec/log:rw diff --git a/yarn-project/aztec/src/cli/cmds/start_pxe.ts b/yarn-project/aztec/src/cli/cmds/start_pxe.ts index f1d8681982c..55bea808d2d 100644 --- a/yarn-project/aztec/src/cli/cmds/start_pxe.ts +++ b/yarn-project/aztec/src/cli/cmds/start_pxe.ts @@ -117,8 +117,5 @@ export async function addPXE( // Add PXE to services list services.pxe = [pxe, PXESchema]; - // Add PXE stop function to signal handlers - signalHandlers.push(pxe.stop); - return pxe; } diff --git a/yarn-project/aztec/src/sandbox.ts b/yarn-project/aztec/src/sandbox.ts index 0545db16714..d720894da3a 100644 --- a/yarn-project/aztec/src/sandbox.ts +++ b/yarn-project/aztec/src/sandbox.ts @@ -157,7 +157,6 @@ export async function createSandbox(config: Partial = {}) { } const stop = async () => { - await pxe.stop(); await node.stop(); await watcher?.stop(); }; diff --git a/yarn-project/bot/src/factory.ts b/yarn-project/bot/src/factory.ts index aac66847624..03098a3095c 100644 --- a/yarn-project/bot/src/factory.ts +++ b/yarn-project/bot/src/factory.ts @@ -6,7 +6,6 @@ import { type DeployOptions, createLogger, createPXEClient, - retryUntil, } from '@aztec/aztec.js'; import { type AztecNode, type FunctionCall, type PXE } from '@aztec/circuit-types'; import { Fr, deriveSigningKey } from '@aztec/circuits.js'; @@ -67,16 +66,6 @@ export class BotFactory { if (isInit) { this.log.info(`Account at ${account.getAddress().toString()} already initialized`); const wallet = await account.register(); - const blockNumber = await this.pxe.getBlockNumber(); - await retryUntil( - async () => { - const status = await this.pxe.getSyncStatus(); - return blockNumber <= status.blocks; - }, - 'pxe synch', - 3600, - 1, - ); return wallet; } else { this.log.info(`Initializing account at ${account.getAddress().toString()}`); diff --git a/yarn-project/circuit-types/src/interfaces/index.ts b/yarn-project/circuit-types/src/interfaces/index.ts index 3f05c960e1b..2b880ad7550 100644 --- a/yarn-project/circuit-types/src/interfaces/index.ts +++ b/yarn-project/circuit-types/src/interfaces/index.ts @@ -18,7 +18,6 @@ export * from './proving-job.js'; export * from './pxe.js'; export * from './server_circuit_prover.js'; export * from './service.js'; -export * from './sync-status.js'; export * from './world_state.js'; export * from './prover-broker.js'; export * from './p2p.js'; diff --git a/yarn-project/circuit-types/src/interfaces/pxe.test.ts b/yarn-project/circuit-types/src/interfaces/pxe.test.ts index 8530f731bd1..9bf3ca99f59 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.test.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.test.ts @@ -43,7 +43,6 @@ import { Tx, TxHash, TxProvingResult, TxReceipt, TxSimulationResult } from '../t import { TxEffect } from '../tx_effect.js'; import { TxExecutionRequest } from '../tx_execution_request.js'; import { type EventMetadataDefinition, type PXE, type PXEInfo, PXESchema } from './pxe.js'; -import { type SyncStatus } from './sync-status.js'; jest.setTimeout(12_000); @@ -258,16 +257,6 @@ describe('PXESchema', () => { expect(result).toEqual(await handler.getPXEInfo()); }); - it('isGlobalStateSynchronized', async () => { - const result = await context.client.isGlobalStateSynchronized(); - expect(result).toBe(true); - }); - - it('getSyncStatus', async () => { - const result = await context.client.getSyncStatus(); - expect(result).toEqual(await handler.getSyncStatus()); - }); - it('getContractInstance', async () => { const result = await context.client.getContractInstance(address); expect(result).toEqual(instance); @@ -502,14 +491,6 @@ class MockPXE implements PXE { pxeVersion: '1.0', }); } - isGlobalStateSynchronized(): Promise { - return Promise.resolve(true); - } - getSyncStatus(): Promise { - return Promise.resolve({ - blocks: 1, - }); - } getContractInstance(address: AztecAddress): Promise { expect(address).toEqual(this.address); return Promise.resolve(this.instance); diff --git a/yarn-project/circuit-types/src/interfaces/pxe.ts b/yarn-project/circuit-types/src/interfaces/pxe.ts index 363511bad80..62c99eb84ba 100644 --- a/yarn-project/circuit-types/src/interfaces/pxe.ts +++ b/yarn-project/circuit-types/src/interfaces/pxe.ts @@ -43,7 +43,6 @@ import { SiblingPath } from '../sibling_path/sibling_path.js'; import { Tx, TxHash, TxProvingResult, TxReceipt, TxSimulationResult } from '../tx/index.js'; import { TxEffect } from '../tx_effect.js'; import { TxExecutionRequest } from '../tx_execution_request.js'; -import { type SyncStatus, SyncStatusSchema } from './sync-status.js'; // docs:start:pxe-interface /** @@ -351,22 +350,6 @@ export interface PXE { */ getPXEInfo(): Promise; - /** - * Checks whether all the blocks were processed (tree roots updated, txs updated with block info, etc.). - * @returns True if there are no outstanding blocks to be synched. - * @remarks This indicates that blocks and transactions are synched even if notes are not. Compares local block number with the block number from aztec node. - * @deprecated Use `getSyncStatus` instead. - */ - isGlobalStateSynchronized(): Promise; - - /** - * Returns the latest block that has been synchronized globally and for each account. The global block number - * indicates whether global state has been updated up to that block, whereas each address indicates up to which - * block the private state has been synced for that account. - * @returns The latest block synchronized for blocks, and the latest block synched for notes for each public key being tracked. - */ - getSyncStatus(): Promise; - /** * Returns a Contract Instance given its address, which includes the contract class identifier, * initialization hash, deployment salt, and public keys hash. @@ -540,8 +523,6 @@ export const PXESchema: ApiSchemaFor = { getProvenBlockNumber: z.function().returns(z.number()), getNodeInfo: z.function().returns(NodeInfoSchema), getPXEInfo: z.function().returns(PXEInfoSchema), - isGlobalStateSynchronized: z.function().returns(z.boolean()), - getSyncStatus: z.function().returns(SyncStatusSchema), getContractInstance: z .function() .args(schemas.AztecAddress) diff --git a/yarn-project/circuit-types/src/interfaces/sync-status.ts b/yarn-project/circuit-types/src/interfaces/sync-status.ts deleted file mode 100644 index b85a13620d6..00000000000 --- a/yarn-project/circuit-types/src/interfaces/sync-status.ts +++ /dev/null @@ -1,13 +0,0 @@ -import { type ZodFor } from '@aztec/foundation/schemas'; - -import { z } from 'zod'; - -/** Provides up to which block has been synced by different components. */ -export type SyncStatus = { - /** Up to which block has been synched for blocks and txs. */ - blocks: number; -}; - -export const SyncStatusSchema = z.object({ - blocks: z.number(), -}) satisfies ZodFor; diff --git a/yarn-project/cli-wallet/src/bin/index.ts b/yarn-project/cli-wallet/src/bin/index.ts index bcdbb4d50a1..1147134a56f 100644 --- a/yarn-project/cli-wallet/src/bin/index.ts +++ b/yarn-project/cli-wallet/src/bin/index.ts @@ -2,7 +2,6 @@ import { Fr, computeSecretHash, fileURLToPath } from '@aztec/aztec.js'; import { LOCALHOST } from '@aztec/cli/cli-utils'; import { type LogFn, createConsoleLogger, createLogger } from '@aztec/foundation/log'; import { AztecLmdbStore } from '@aztec/kv-store/lmdb'; -import { type PXEService } from '@aztec/pxe'; import { Argument, Command, Option } from 'commander'; import { readFileSync } from 'fs'; @@ -94,11 +93,6 @@ async function main() { await pxeWrapper.init(nodeUrl, join(dataDir, 'pxe')); } db.init(AztecLmdbStore.open(dataDir)); - }) - .hook('postAction', async () => { - if (pxeWrapper.getPXE()) { - await (pxeWrapper.getPXE() as PXEService).stop(); - } }); injectCommands(program, userLog, debugLogger, db, pxeWrapper); diff --git a/yarn-project/cli/src/cmds/pxe/get_block.ts b/yarn-project/cli/src/cmds/pxe/get_block.ts index d1584950ff1..f2951a9c8f6 100644 --- a/yarn-project/cli/src/cmds/pxe/get_block.ts +++ b/yarn-project/cli/src/cmds/pxe/get_block.ts @@ -3,29 +3,8 @@ import { type LogFn, type Logger } from '@aztec/foundation/log'; import { inspectBlock } from '../../utils/inspect.js'; -export async function getBlock( - rpcUrl: string, - maybeBlockNumber: number | undefined, - follow: boolean, - debugLogger: Logger, - log: LogFn, -) { +export async function getBlock(rpcUrl: string, maybeBlockNumber: number | undefined, debugLogger: Logger, log: LogFn) { const client = await createCompatibleClient(rpcUrl, debugLogger); const blockNumber = maybeBlockNumber ?? (await client.getBlockNumber()); await inspectBlock(client, blockNumber, log, { showTxs: true }); - - if (follow) { - let lastBlock = blockNumber; - setInterval(async () => { - const newBlock = await client.getBlockNumber(); - if (newBlock > lastBlock) { - const { blocks } = await client.getSyncStatus(); - if (blocks >= newBlock) { - log(''); - await inspectBlock(client, newBlock, log, { showTxs: true }); - lastBlock = newBlock; - } - } - }, 1000); - } } diff --git a/yarn-project/cli/src/cmds/pxe/index.ts b/yarn-project/cli/src/cmds/pxe/index.ts index e6e1f862725..dc8a7a4bb6a 100644 --- a/yarn-project/cli/src/cmds/pxe/index.ts +++ b/yarn-project/cli/src/cmds/pxe/index.ts @@ -54,11 +54,10 @@ export function injectCommands(program: Command, log: LogFn, debugLogger: Logger .command('get-block') .description('Gets info for a given block or latest.') .argument('[blockNumber]', 'Block height', parseOptionalInteger) - .option('-f, --follow', 'Keep polling for new blocks') .addOption(pxeOption) .action(async (blockNumber, options) => { const { getBlock } = await import('./get_block.js'); - await getBlock(options.rpcUrl, blockNumber, options.follow, debugLogger, log); + await getBlock(options.rpcUrl, blockNumber, debugLogger, log); }); program diff --git a/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml b/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml index 2fbbabb4d6d..b219e4d01de 100644 --- a/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml +++ b/yarn-project/end-to-end/scripts/docker-compose-no-sandbox.yml @@ -18,7 +18,6 @@ services: P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 WS_BLOCK_CHECK_INTERVAL_MS: 50 - PXE_BLOCK_POLLING_INTERVAL_MS: 50 ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 ENABLE_GAS: ${ENABLE_GAS:-''} JOB_NAME: ${JOB_NAME:-''} diff --git a/yarn-project/end-to-end/scripts/docker-compose-wallet.yml b/yarn-project/end-to-end/scripts/docker-compose-wallet.yml index b1a421ed575..d7e4541e7fb 100644 --- a/yarn-project/end-to-end/scripts/docker-compose-wallet.yml +++ b/yarn-project/end-to-end/scripts/docker-compose-wallet.yml @@ -18,7 +18,6 @@ services: P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 WS_BLOCK_CHECK_INTERVAL_MS: 50 - PXE_BLOCK_POLLING_INTERVAL_MS: 50 ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 ENABLE_GAS: ${ENABLE_GAS:-} HARDWARE_CONCURRENCY: ${HARDWARE_CONCURRENCY:-} diff --git a/yarn-project/end-to-end/scripts/docker-compose.yml b/yarn-project/end-to-end/scripts/docker-compose.yml index 4a96de1088d..eae41741bb5 100644 --- a/yarn-project/end-to-end/scripts/docker-compose.yml +++ b/yarn-project/end-to-end/scripts/docker-compose.yml @@ -18,7 +18,6 @@ services: P2P_BLOCK_CHECK_INTERVAL_MS: 50 SEQ_TX_POLLING_INTERVAL_MS: 50 WS_BLOCK_CHECK_INTERVAL_MS: 50 - PXE_BLOCK_POLLING_INTERVAL_MS: 50 ARCHIVER_VIEM_POLLING_INTERVAL_MS: 500 ENABLE_GAS: ${ENABLE_GAS:-} HARDWARE_CONCURRENCY: ${HARDWARE_CONCURRENCY:-} diff --git a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts index adc29c28d63..167548937a7 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_process_history.test.ts @@ -9,7 +9,7 @@ import { type BenchmarkingContract } from '@aztec/noir-contracts.js/Benchmarking import { type SequencerClient } from '@aztec/sequencer-client'; import { type EndToEndContext } from '../fixtures/utils.js'; -import { benchmarkSetup, getFolderSize, makeDataDirectory, sendTxs, waitNewPXESynced } from './utils.js'; +import { benchmarkSetup, createNewPXE, getFolderSize, makeDataDirectory, sendTxs } from './utils.js'; const BLOCK_SIZE = BENCHMARK_HISTORY_BLOCK_SIZE; const CHAIN_LENGTHS = BENCHMARK_HISTORY_CHAIN_LENGTHS; @@ -69,7 +69,7 @@ describe('benchmarks/process_history', () => { // Create a new pxe and measure how much time it takes it to sync with failed and successful decryption // Skip the first two blocks used for setup (create account contract and deploy benchmarking contract) context.logger.info(`Starting new pxe`); - const pxe = await waitNewPXESynced(node, contract, INITIAL_L2_BLOCK_NUM + setupBlockCount); + const pxe = await createNewPXE(node, contract, INITIAL_L2_BLOCK_NUM + setupBlockCount); // Register the owner account and wait until it's synced so we measure how much time it took context.logger.info(`Registering owner account on new pxe`); @@ -81,8 +81,7 @@ describe('benchmarks/process_history', () => { context.logger.info(`Registering fresh account on new pxe`); await pxe.registerAccount(Fr.random(), Fr.random()); - // Stop the external node and pxe - await pxe.stop(); + // Stop the external node await node.stop(); lastBlock = chainLength; diff --git a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts index d77451f317f..49a09404359 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_prover.test.ts @@ -177,9 +177,6 @@ describe('benchmarks/proving', () => { }); afterAll(async () => { - for (const pxe of provingPxes) { - await pxe.stop(); - } await ctx.teardown(); await acvmCleanup(); await bbCleanup(); diff --git a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts index 21612ccbe85..97d7fb4b17b 100644 --- a/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts +++ b/yarn-project/end-to-end/src/benchmarks/bench_publish_rollup.test.ts @@ -5,7 +5,7 @@ import { type BenchmarkingContract } from '@aztec/noir-contracts.js/Benchmarking import { type SequencerClient } from '@aztec/sequencer-client'; import { type EndToEndContext } from '../fixtures/utils.js'; -import { benchmarkSetup, sendTxs, waitNewPXESynced } from './utils.js'; +import { benchmarkSetup, createNewPXE, sendTxs } from './utils.js'; describe('benchmarks/publish_rollup', () => { let context: EndToEndContext; @@ -41,7 +41,7 @@ describe('benchmarks/publish_rollup', () => { // Spin up a new pxe and sync it, we'll use it to test sync times of new accounts for the last block context.logger.info(`Starting new pxe`); - const pxe = await waitNewPXESynced(node, contract, blockNumber! - 1); + const pxe = await createNewPXE(node, contract, blockNumber! - 1); // Register the owner account and wait until it's synced so we measure how much time it took context.logger.info(`Registering owner account on new pxe`); @@ -53,8 +53,7 @@ describe('benchmarks/publish_rollup', () => { context.logger.info(`Registering fresh account on new pxe`); await pxe.registerAccount(Fr.random(), Fr.random()); - // Stop the external node and pxe - await pxe.stop(); + // Stop the external node await node.stop(); }, 20 * 60_000, diff --git a/yarn-project/end-to-end/src/benchmarks/utils.ts b/yarn-project/end-to-end/src/benchmarks/utils.ts index 5dbebfa26ce..05c90892ae7 100644 --- a/yarn-project/end-to-end/src/benchmarks/utils.ts +++ b/yarn-project/end-to-end/src/benchmarks/utils.ts @@ -1,5 +1,5 @@ import { type AztecNodeConfig, type AztecNodeService } from '@aztec/aztec-node'; -import { type AztecNode, BatchCall, INITIAL_L2_BLOCK_NUM, type SentTx, retryUntil, sleep } from '@aztec/aztec.js'; +import { type AztecNode, BatchCall, INITIAL_L2_BLOCK_NUM, type SentTx, sleep } from '@aztec/aztec.js'; import { times } from '@aztec/foundation/collection'; import { randomInt } from '@aztec/foundation/crypto'; import { BenchmarkingContract } from '@aztec/noir-contracts.js/Benchmarking'; @@ -90,13 +90,13 @@ export async function sendTxs( } /** - * Creates a new PXE and awaits until it's synced with the node. + * Creates a new PXE * @param node - Node to connect the pxe to. * @param contract - Benchmark contract to add to the pxe. * @param startingBlock - First l2 block to process. * @returns The new PXE. */ -export async function waitNewPXESynced( +export async function createNewPXE( node: AztecNode, contract: BenchmarkingContract, startingBlock: number = INITIAL_L2_BLOCK_NUM, @@ -111,6 +111,5 @@ export async function waitNewPXESynced( } as PXEServiceConfig; const pxe = await createPXEService(node, pxeConfig); await pxe.registerContract(contract); - await retryUntil(() => pxe.isGlobalStateSynchronized(), 'pxe-global-sync'); return pxe; } diff --git a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts index 87528585bd1..eaa70fa10ff 100644 --- a/yarn-project/end-to-end/src/e2e_2_pxes.test.ts +++ b/yarn-project/end-to-end/src/e2e_2_pxes.test.ts @@ -8,7 +8,6 @@ import { type Logger, type PXE, type Wallet, - retryUntil, sleep, } from '@aztec/aztec.js'; import { ChildContract, TestContract, TokenContract } from '@aztec/noir-contracts.js'; @@ -57,8 +56,7 @@ describe('e2e_2_pxes', () => { await teardownA(); }); - // TODO #10296 - it.skip('transfers funds from user A to B via PXE A followed by transfer from B to A via PXE B', async () => { + it('transfers funds from user A to B via PXE A followed by transfer from B to A via PXE B', async () => { const initialBalance = 987n; const transferAmount1 = 654n; const transferAmount2 = 323n; @@ -103,21 +101,12 @@ describe('e2e_2_pxes', () => { return contract.instance; }; - const awaitServerSynchronized = async (server: PXE) => { - const isServerSynchronized = async () => { - return await server.isGlobalStateSynchronized(); - }; - await retryUntil(isServerSynchronized, 'server sync', 10); - }; - const getChildStoredValue = (child: { address: AztecAddress }, pxe: PXE) => pxe.getPublicStorageAt(child.address, new Fr(1)); it('user calls a public function on a contract deployed by a different user using a different PXE', async () => { const childCompleteAddress = await deployChildContractViaServerA(); - await awaitServerSynchronized(pxeA); - // Add Child to PXE B await pxeB.registerContract({ artifact: ChildContract.artifact, @@ -129,8 +118,6 @@ describe('e2e_2_pxes', () => { const childContractWithWalletB = await ChildContract.at(childCompleteAddress.address, walletB); await childContractWithWalletB.methods.pub_inc_value(newValueToSet).send().wait({ interval: 0.1 }); - await awaitServerSynchronized(pxeA); - const storedValueOnB = await getChildStoredValue(childCompleteAddress, pxeB); expect(storedValueOnB).toEqual(newValueToSet); diff --git a/yarn-project/end-to-end/src/e2e_block_building.test.ts b/yarn-project/end-to-end/src/e2e_block_building.test.ts index 38ff8cce2e1..942e558d83e 100644 --- a/yarn-project/end-to-end/src/e2e_block_building.test.ts +++ b/yarn-project/end-to-end/src/e2e_block_building.test.ts @@ -483,14 +483,6 @@ describe('e2e_block_building', () => { // PXE should have cleared out the 30-note from tx2, but reapplied the 20-note from tx1 expect(await contract.methods.summed_values(ownerAddress).simulate()).toEqual(21n); - // PXE should be synced to the block number on the new chain - await retryUntil( - async () => (await pxe.getSyncStatus()).blocks === newTx1Receipt.blockNumber, - 'wait for pxe block header sync', - 15, - 1, - ); - // And we should be able to send a new tx on the new chain logger.info('Sending new tx on reorgd chain'); const tx3 = await contract.methods.create_note(ownerAddress, ownerAddress, 10).send().wait(); diff --git a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts index 7a0507a6e63..6743a7ef2c4 100644 --- a/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts +++ b/yarn-project/end-to-end/src/fixtures/snapshot_manager.ts @@ -247,7 +247,6 @@ async function teardown(context: SubsystemsContext | undefined) { getLogger().info('Tearing down subsystems'); await context.proverNode?.stop(); await context.aztecNode.stop(); - await context.pxe.stop(); await context.acvmConfig?.cleanup(); await context.anvil.stop(); await context.watcher.stop(); diff --git a/yarn-project/end-to-end/src/fixtures/utils.ts b/yarn-project/end-to-end/src/fixtures/utils.ts index 8c71ccb4d9a..b8954d38cd1 100644 --- a/yarn-project/end-to-end/src/fixtures/utils.ts +++ b/yarn-project/end-to-end/src/fixtures/utils.ts @@ -42,7 +42,7 @@ import { FeeJuiceContract } from '@aztec/noir-contracts.js/FeeJuice'; import { getVKTreeRoot } from '@aztec/noir-protocol-circuits-types'; import { ProtocolContractAddress, protocolContractTreeRoot } from '@aztec/protocol-contracts'; import { type ProverNode, type ProverNodeConfig, createProverNode } from '@aztec/prover-node'; -import { PXEService, type PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe'; +import { type PXEService, type PXEServiceConfig, createPXEService, getPXEServiceConfig } from '@aztec/pxe'; import { type SequencerClient, TestL1Publisher } from '@aztec/sequencer-client'; import { NoopTelemetryClient } from '@aztec/telemetry-client/noop'; import { createAndStartTelemetryClient, getConfigEnvVars as getTelemetryConfig } from '@aztec/telemetry-client/start'; @@ -146,9 +146,7 @@ export async function setupPXEService( const pxeServiceConfig = { ...getPXEServiceConfig(), ...opts }; const pxe = await createPXEService(aztecNode, pxeServiceConfig, useLogSuffix, proofCreator); - const teardown = async () => { - await pxe.stop(); - }; + const teardown = async () => {}; return { pxe, @@ -445,9 +443,6 @@ export async function setup( if (aztecNode instanceof AztecNodeService) { await aztecNode?.stop(); } - if (pxe instanceof PXEService) { - await pxe?.stop(); - } if (acvmConfig?.cleanup) { // remove the temp directory created for the acvm diff --git a/yarn-project/foundation/src/config/env_var.ts b/yarn-project/foundation/src/config/env_var.ts index cb43781825f..ea13f2f9711 100644 --- a/yarn-project/foundation/src/config/env_var.ts +++ b/yarn-project/foundation/src/config/env_var.ts @@ -126,7 +126,6 @@ export type EnvVar = | 'PROVER_REQUIRED_CONFIRMATIONS' | 'PROVER_TEST_DELAY_MS' | 'PROVER_CACHE_DIR' - | 'PXE_BLOCK_POLLING_INTERVAL_MS' | 'PXE_L2_STARTING_BLOCK' | 'PXE_PROVER_ENABLED' | 'QUOTE_PROVIDER_BASIS_POINT_FEE' diff --git a/yarn-project/pxe/src/bin/index.ts b/yarn-project/pxe/src/bin/index.ts index 5ba7ce5aa0e..66f451dae92 100644 --- a/yarn-project/pxe/src/bin/index.ts +++ b/yarn-project/pxe/src/bin/index.ts @@ -5,7 +5,7 @@ import { createLogger } from '@aztec/foundation/log'; import { getPXEServiceConfig } from '../config/index.js'; import { startPXEHttpServer } from '../pxe_http/index.js'; -import { createPXEService } from '../utils/index.js'; +import { createPXEService } from '../utils/create_pxe_service.js'; const { PXE_PORT = 8080, AZTEC_NODE_URL = 'http://localhost:8079' } = process.env; @@ -23,9 +23,8 @@ async function main() { const nodeRpcClient = createAztecNodeClient(AZTEC_NODE_URL); const pxeService = await createPXEService(nodeRpcClient, pxeConfig); - const shutdown = async () => { + const shutdown = () => { logger.info('Shutting down...'); - await pxeService.stop(); process.exit(0); }; diff --git a/yarn-project/pxe/src/config/index.ts b/yarn-project/pxe/src/config/index.ts index 4841f7ce6fd..7eeb270453f 100644 --- a/yarn-project/pxe/src/config/index.ts +++ b/yarn-project/pxe/src/config/index.ts @@ -28,8 +28,6 @@ export interface KernelProverConfig { * Configuration settings for the PXE. */ export interface PXEConfig { - /** The interval to wait between polling for new blocks. */ - l2BlockPollingIntervalMS: number; /** L2 block to start scanning from for new accounts */ l2StartingBlock: number; } @@ -47,11 +45,6 @@ export type CliPXEOptions = { export const pxeConfigMappings: ConfigMappingsType = { ...dataConfigMappings, - l2BlockPollingIntervalMS: { - env: 'PXE_BLOCK_POLLING_INTERVAL_MS', - description: 'The interval to wait between polling for new blocks.', - ...numberConfigHelper(1_000), - }, l2StartingBlock: { env: 'PXE_L2_STARTING_BLOCK', ...numberConfigHelper(INITIAL_L2_BLOCK_NUM), diff --git a/yarn-project/pxe/src/database/kv_pxe_database.ts b/yarn-project/pxe/src/database/kv_pxe_database.ts index 866d2df92c7..5439afa717b 100644 --- a/yarn-project/pxe/src/database/kv_pxe_database.ts +++ b/yarn-project/pxe/src/database/kv_pxe_database.ts @@ -46,7 +46,6 @@ export class KVPxeDatabase implements PxeDatabase { #nullifiedNotesByTxHash: AztecAsyncMultiMap; #nullifiedNotesByAddressPoint: AztecAsyncMultiMap; #nullifiedNotesByNullifier: AztecAsyncMap; - #syncedBlockPerPublicKey: AztecAsyncMap; #contractArtifacts: AztecAsyncMap; #contractInstances: AztecAsyncMap; #db: AztecAsyncKVStore; @@ -79,7 +78,6 @@ export class KVPxeDatabase implements PxeDatabase { this.#contractInstances = db.openMap('contracts_instances'); this.#synchronizedBlock = db.openSingleton('header'); - this.#syncedBlockPerPublicKey = db.openMap('synced_block_per_public_key'); this.#notes = db.openMap('notes'); this.#nullifiedNotes = db.openMap('nullified_notes'); @@ -564,14 +562,6 @@ export class KVPxeDatabase implements PxeDatabase { return true; } - getSynchedBlockNumberForAccount(account: AztecAddress): Promise { - return this.#syncedBlockPerPublicKey.getAsync(account.toString()); - } - - setSynchedBlockNumberForAccount(account: AztecAddress, blockNumber: number): Promise { - return this.#syncedBlockPerPublicKey.set(account.toString(), blockNumber); - } - async estimateSize(): Promise { const incomingNotesSize = (await this.getIncomingNotes({})).reduce((sum, note) => sum + note.getSize(), 0); diff --git a/yarn-project/pxe/src/database/pxe_database.ts b/yarn-project/pxe/src/database/pxe_database.ts index 0b24e77b99a..4f2fd1557f2 100644 --- a/yarn-project/pxe/src/database/pxe_database.ts +++ b/yarn-project/pxe/src/database/pxe_database.ts @@ -160,19 +160,6 @@ export interface PxeDatabase extends ContractArtifactDatabase, ContractInstanceD */ getCompleteAddresses(): Promise; - /** - * Updates up to which block number we have processed notes for a given public key. - * @param account - The account to set the synched block number for. - * @param blockNumber - The block number to set. - */ - setSynchedBlockNumberForAccount(account: AztecAddress, blockNumber: number): Promise; - - /** - * Get the synched block number for a given public key. - * @param account - The account to get the synched block number for. - */ - getSynchedBlockNumberForAccount(account: AztecAddress): Promise; - /** * Returns the estimated size in bytes of this db. * @returns The estimated size in bytes of this db. diff --git a/yarn-project/pxe/src/index.ts b/yarn-project/pxe/src/index.ts index d0bdaa737a6..e97f38565f2 100644 --- a/yarn-project/pxe/src/index.ts +++ b/yarn-project/pxe/src/index.ts @@ -1,6 +1,7 @@ export * from './pxe_service/index.js'; export * from './pxe_http/index.js'; export * from './config/index.js'; +export * from './utils/create_pxe_service.js'; export { Tx, TxHash } from '@aztec/circuit-types'; @@ -10,7 +11,6 @@ export * from '@aztec/foundation/eth-address'; export * from '@aztec/foundation/aztec-address'; export * from '@aztec/key-store'; export * from './database/index.js'; -export * from './utils/index.js'; export { ContractDataOracle } from './contract_data_oracle/index.js'; export { PrivateFunctionsTree } from './contract_data_oracle/private_functions_tree.js'; export { SimulatorOracle } from './simulator_oracle/index.js'; diff --git a/yarn-project/pxe/src/pxe_service/pxe_service.ts b/yarn-project/pxe/src/pxe_service/pxe_service.ts index 9c63173a600..f2b1f419909 100644 --- a/yarn-project/pxe/src/pxe_service/pxe_service.ts +++ b/yarn-project/pxe/src/pxe_service/pxe_service.ts @@ -56,7 +56,6 @@ import { } from '@aztec/foundation/abi'; import { Fr, type Point } from '@aztec/foundation/fields'; import { type Logger, createLogger } from '@aztec/foundation/log'; -import { SerialQueue } from '@aztec/foundation/queue'; import { type KeyStore } from '@aztec/key-store'; import { type L2TipsStore } from '@aztec/kv-store/stores'; import { @@ -89,9 +88,6 @@ export class PXEService implements PXE { private simulator: AcirSimulator; private log: Logger; private packageVersion: string; - // serialize synchronizer and calls to proveTx. - // ensures that state is not changed while simulating - private jobQueue = new SerialQueue(); constructor( private keyStore: KeyStore, @@ -107,8 +103,6 @@ export class PXEService implements PXE { this.contractDataOracle = new ContractDataOracle(db); this.simulator = getAcirSimulator(db, node, keyStore, this.contractDataOracle); this.packageVersion = getPackageInfo().version; - - this.jobQueue.start(); } /** @@ -116,27 +110,12 @@ export class PXEService implements PXE { * * @returns A promise that resolves when the server has started successfully. */ - public async start() { - await this.synchronizer.start(); + public async init() { await this.#registerProtocolContracts(); const info = await this.getNodeInfo(); this.log.info(`Started PXE connected to chain ${info.l1ChainId} version ${info.protocolVersion}`); } - /** - * Stops the PXE Service, halting processing of new transactions and shutting down the synchronizer. - * This function ensures that all ongoing tasks are completed before stopping the server. - * It is useful for gracefully shutting down the server during maintenance or restarts. - * - * @returns A Promise resolving once the server has been stopped successfully. - */ - public async stop() { - await this.jobQueue.cancel(); - this.log.info('Cancelled Job Queue'); - await this.synchronizer.stop(); - this.log.info('Stopped Synchronizer'); - } - isL1ToL2MessageSynced(l1ToL2Message: Fr): Promise { return this.node.isL1ToL2MessageSynced(l1ToL2Message); } @@ -484,22 +463,16 @@ export class PXEService implements PXE { return result.publicInputs; } - public proveTx( + public async proveTx( txRequest: TxExecutionRequest, privateExecutionResult: PrivateExecutionResult, ): Promise { - return this.jobQueue - .put(async () => { - const { publicInputs, clientIvcProof } = await this.#prove( - txRequest, - this.proofCreator, - privateExecutionResult, - ); - return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof!); - }) - .catch(err => { - throw this.contextualizeError(err, inspect(txRequest), inspect(privateExecutionResult)); - }); + try { + const { publicInputs, clientIvcProof } = await this.#prove(txRequest, this.proofCreator, privateExecutionResult); + return new TxProvingResult(privateExecutionResult, publicInputs, clientIvcProof!); + } catch (err: any) { + throw this.contextualizeError(err, inspect(txRequest), inspect(privateExecutionResult)); + } } // TODO(#7456) Prevent msgSender being defined here for the first call @@ -511,78 +484,77 @@ export class PXEService implements PXE { profile: boolean = false, scopes?: AztecAddress[], ): Promise { - return await this.jobQueue - .put(async () => { - const txInfo = { - origin: txRequest.origin, - functionSelector: txRequest.functionSelector, - simulatePublic, - msgSender, - chainId: txRequest.txContext.chainId, - version: txRequest.txContext.version, - authWitnesses: txRequest.authWitnesses.map(w => w.requestHash), - }; - this.log.verbose( - `Simulating transaction execution request to ${txRequest.functionSelector} at ${txRequest.origin}`, - txInfo, - ); - const privateExecutionResult = await this.#executePrivate(txRequest, msgSender, scopes); - - let publicInputs: PrivateKernelTailCircuitPublicInputs; - let profileResult; - if (profile) { - ({ publicInputs, profileResult } = await this.#profileKernelProver( - txRequest, - this.proofCreator, - privateExecutionResult, - )); - } else { - publicInputs = await this.#simulateKernels(txRequest, privateExecutionResult); - } + try { + const txInfo = { + origin: txRequest.origin, + functionSelector: txRequest.functionSelector, + simulatePublic, + msgSender, + chainId: txRequest.txContext.chainId, + version: txRequest.txContext.version, + authWitnesses: txRequest.authWitnesses.map(w => w.requestHash), + }; + this.log.verbose( + `Simulating transaction execution request to ${txRequest.functionSelector} at ${txRequest.origin}`, + txInfo, + ); + await this.synchronizer.sync(); + const privateExecutionResult = await this.#executePrivate(txRequest, msgSender, scopes); - const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs); - const simulatedTx = privateSimulationResult.toSimulatedTx(); - let publicOutput: PublicSimulationOutput | undefined; - if (simulatePublic) { - publicOutput = await this.#simulatePublicCalls(simulatedTx); - } + let publicInputs: PrivateKernelTailCircuitPublicInputs; + let profileResult; + if (profile) { + ({ publicInputs, profileResult } = await this.#profileKernelProver( + txRequest, + this.proofCreator, + privateExecutionResult, + )); + } else { + publicInputs = await this.#simulateKernels(txRequest, privateExecutionResult); + } - if (!skipTxValidation) { - if (!(await this.node.isValidTx(simulatedTx, true))) { - throw new Error('The simulated transaction is unable to be added to state and is invalid.'); - } + const privateSimulationResult = new PrivateSimulationResult(privateExecutionResult, publicInputs); + const simulatedTx = privateSimulationResult.toSimulatedTx(); + let publicOutput: PublicSimulationOutput | undefined; + if (simulatePublic) { + publicOutput = await this.#simulatePublicCalls(simulatedTx); + } + + if (!skipTxValidation) { + if (!(await this.node.isValidTx(simulatedTx, true))) { + throw new Error('The simulated transaction is unable to be added to state and is invalid.'); } + } - this.log.info(`Simulation completed for ${simulatedTx.tryGetTxHash()}`, { - txHash: simulatedTx.tryGetTxHash(), - ...txInfo, - ...(profileResult ? { gateCounts: profileResult.gateCounts } : {}), - ...(publicOutput - ? { - gasUsed: publicOutput.gasUsed, - revertCode: publicOutput.txEffect.revertCode.getCode(), - revertReason: publicOutput.revertReason, - } - : {}), - }); - - return TxSimulationResult.fromPrivateSimulationResultAndPublicOutput( - privateSimulationResult, - publicOutput, - profileResult, - ); - }) - .catch(err => { - throw this.contextualizeError( - err, - inspect(txRequest), - `simulatePublic=${simulatePublic}`, - `msgSender=${msgSender?.toString() ?? 'undefined'}`, - `skipTxValidation=${skipTxValidation}`, - `profile=${profile}`, - `scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`, - ); + this.log.info(`Simulation completed for ${simulatedTx.tryGetTxHash()}`, { + txHash: simulatedTx.tryGetTxHash(), + ...txInfo, + ...(profileResult ? { gateCounts: profileResult.gateCounts } : {}), + ...(publicOutput + ? { + gasUsed: publicOutput.gasUsed, + revertCode: publicOutput.txEffect.revertCode.getCode(), + revertReason: publicOutput.revertReason, + } + : {}), }); + + return TxSimulationResult.fromPrivateSimulationResultAndPublicOutput( + privateSimulationResult, + publicOutput, + profileResult, + ); + } catch (err: any) { + throw this.contextualizeError( + err, + inspect(txRequest), + `simulatePublic=${simulatePublic}`, + `msgSender=${msgSender?.toString() ?? 'undefined'}`, + `skipTxValidation=${skipTxValidation}`, + `profile=${profile}`, + `scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`, + ); + } } public async sendTx(tx: Tx): Promise { @@ -605,24 +577,22 @@ export class PXEService implements PXE { _from?: AztecAddress, scopes?: AztecAddress[], ): Promise { - // all simulations must be serialized w.r.t. the synchronizer - return await this.jobQueue - .put(async () => { - // TODO - Should check if `from` has the permission to call the view function. - const functionCall = await this.#getFunctionCall(functionName, args, to); - const executionResult = await this.#simulateUnconstrained(functionCall, scopes); - - // TODO - Return typed result based on the function artifact. - return executionResult; - }) - .catch(err => { - const stringifiedArgs = args.map(arg => arg.toString()).join(', '); - throw this.contextualizeError( - err, - `simulateUnconstrained ${to}:${functionName}(${stringifiedArgs})`, - `scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`, - ); - }); + try { + await this.synchronizer.sync(); + // TODO - Should check if `from` has the permission to call the view function. + const functionCall = await this.#getFunctionCall(functionName, args, to); + const executionResult = await this.#simulateUnconstrained(functionCall, scopes); + + // TODO - Return typed result based on the function artifact. + return executionResult; + } catch (err: any) { + const stringifiedArgs = args.map(arg => arg.toString()).join(', '); + throw this.contextualizeError( + err, + `simulateUnconstrained ${to}:${functionName}(${stringifiedArgs})`, + `scopes=${scopes?.map(s => s.toString()).join(', ') ?? 'undefined'}`, + ); + } } public getTxReceipt(txHash: TxHash): Promise { @@ -726,7 +696,7 @@ export class PXEService implements PXE { await this.db.addContractInstance(instance); registered[name] = address.toString(); } - this.log.info(`Registered protocol contracts in pxe`, registered); + this.log.verbose(`Registered protocol contracts in pxe`, registered); } /** @@ -840,19 +810,14 @@ export class PXEService implements PXE { } /** - * Simulate a transaction, generate a kernel proof, and create a private transaction object. - * The function takes in a transaction request, simulates it, and then generates a kernel proof - * using the simulation result. Finally, it creates a private - * transaction object with the generated proof and public inputs. If a new contract address is provided, - * the function will also include the new contract's public functions in the transaction object. + * Generate a kernel proof, and create a private kernel output. + * The function takes in a transaction execution request, and the result of private execution + * and then generates a kernel proof. * * @param txExecutionRequest - The transaction request to be simulated and proved. * @param proofCreator - The proof creator to use for proving the execution. - * @param msgSender - (Optional) The message sender to use for the simulation. - * @param scopes - The accounts whose notes we can access in this call. Currently optional and will default to all. - * @returns An object that contains: - * A private transaction object containing the proof, public inputs, and encrypted logs. - * The return values of the private execution + * @param privateExecutionResult - The result of the private execution + * @returns An object that contains the output of the kernel execution, including the ClientIvcProof if proving is enabled. */ async #prove( txExecutionRequest: TxExecutionRequest, @@ -867,14 +832,6 @@ export class PXEService implements PXE { return await kernelProver.prove(txExecutionRequest.toTxRequest(), privateExecutionResult); } - public async isGlobalStateSynchronized() { - return await this.synchronizer.isGlobalStateSynchronized(); - } - - public getSyncStatus() { - return Promise.resolve(this.synchronizer.getSyncStatus()); - } - public async isContractClassPubliclyRegistered(id: Fr): Promise { return !!(await this.node.getContractClass(id)); } diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts index 678f6c4bb76..d0dc0103bbf 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_service.test.ts @@ -22,7 +22,6 @@ async function createPXEService(): Promise { const db = await KVPxeDatabase.create(kvStore); const tips = new L2TipsStore(kvStore, 'pxe'); const config: PXEServiceConfig = { - l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM, dataDirectory: undefined, dataStoreMapSizeKB: 1024 * 1024, @@ -67,7 +66,6 @@ describe('PXEService', () => { tips = new L2TipsStore(kvStore, 'pxe'); db = await KVPxeDatabase.create(kvStore); config = { - l2BlockPollingIntervalMS: 100, l2StartingBlock: INITIAL_L2_BLOCK_NUM, proverEnabled: false, dataDirectory: undefined, diff --git a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts index c5fc6219e01..686c5b9f9a1 100644 --- a/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts +++ b/yarn-project/pxe/src/pxe_service/test/pxe_test_suite.ts @@ -115,8 +115,5 @@ export const pxeTestSuite = (testName: string, pxeSetup: () => Promise) => expect(typeof nodeInfo.l1ChainId).toEqual('number'); expect(nodeInfo.l1ContractAddresses.rollupAddress.toString()).toMatch(/0x[a-fA-F0-9]+/); }); - - // Note: Not testing `isGlobalStateSynchronized`, `isAccountStateSynchronized` and `getSyncStatus` as these methods - // only call synchronizer. }); }; diff --git a/yarn-project/pxe/src/simulator_oracle/index.ts b/yarn-project/pxe/src/simulator_oracle/index.ts index b6866e9a28c..d05451f87ec 100644 --- a/yarn-project/pxe/src/simulator_oracle/index.ts +++ b/yarn-project/pxe/src/simulator_oracle/index.ts @@ -231,7 +231,7 @@ export class SimulatorOracle implements DBOracle { * @returns A Promise that resolves to a BlockHeader object. */ getBlockHeader(): Promise { - return Promise.resolve(this.db.getBlockHeader()); + return this.db.getBlockHeader(); } /** diff --git a/yarn-project/pxe/src/synchronizer/synchronizer.ts b/yarn-project/pxe/src/synchronizer/synchronizer.ts index a4f13e1d019..225787866df 100644 --- a/yarn-project/pxe/src/synchronizer/synchronizer.ts +++ b/yarn-project/pxe/src/synchronizer/synchronizer.ts @@ -12,14 +12,12 @@ import { type PXEConfig } from '../config/index.js'; import { type PxeDatabase } from '../database/index.js'; /** - * The Synchronizer class manages the synchronization of note processors and interacts with the Aztec node - * to obtain encrypted logs, blocks, and other necessary information for the accounts. - * It provides methods to start or stop the synchronization process, add new accounts, retrieve account - * details, and fetch transactions by hash. The Synchronizer ensures that it maintains the note processors - * in sync with the blockchain while handling retries and errors gracefully. + * The Synchronizer class manages the synchronization with the aztec node, allowing PXE to retrieve the + * latest block header and handle reorgs. + * It provides methods to trigger a sync and get the block number we are syncec to + * details, and fetch transactions by hash. */ export class Synchronizer implements L2BlockStreamEventHandler { - private running = false; private initialSyncBlockNumber = INITIAL_L2_BLOCK_NUM - 1; private log: Logger; protected readonly blockStream: L2BlockStream; @@ -28,16 +26,15 @@ export class Synchronizer implements L2BlockStreamEventHandler { private node: AztecNode, private db: PxeDatabase, private l2TipsStore: L2TipsStore, - config: Partial> = {}, + config: Partial> = {}, logSuffix?: string, ) { this.log = createLogger(logSuffix ? `pxe:synchronizer:${logSuffix}` : 'pxe:synchronizer'); this.blockStream = this.createBlockStream(config); } - protected createBlockStream(config: Partial>) { + protected createBlockStream(config: Partial>) { return new L2BlockStream(this.node, this.l2TipsStore, this, createLogger('pxe:block_stream'), { - pollIntervalMS: config.l2BlockPollingIntervalMS, startingBlock: config.l2StartingBlock, }); } @@ -73,19 +70,10 @@ export class Synchronizer implements L2BlockStreamEventHandler { } /** - * Starts the synchronization process by fetching encrypted logs and blocks from a specified position. - * Continuously processes the fetched data for all note processors until stopped. If there is no data - * available, it retries after a specified interval. - * - * @param limit - The maximum number of encrypted, unencrypted logs and blocks to fetch in each iteration. - * @param retryInterval - The time interval (in ms) to wait before retrying if no data is available. + * Syncs PXE and the node by dowloading the metadata of the latest blocks, allowing simulations to use + * recent data (e.g. notes), and handling any reorgs that might have occurred. */ - public async start() { - if (this.running) { - return; - } - this.running = true; - + public async sync() { let currentHeader; try { @@ -97,54 +85,10 @@ export class Synchronizer implements L2BlockStreamEventHandler { // REFACTOR: We should know the header of the genesis block without having to request it from the node. await this.db.setHeader(await this.node.getBlockHeader(0)); } - - await this.trigger(); - this.log.info('Initial sync complete'); - this.blockStream.start(); - this.log.debug('Started loop'); - } - - /** - * Stops the synchronizer gracefully, interrupting any ongoing sleep and waiting for the current - * iteration to complete before setting the running state to false. Once stopped, the synchronizer - * will no longer process blocks or encrypted logs and must be restarted using the start method. - * - * @returns A promise that resolves when the synchronizer has successfully stopped. - */ - public async stop() { - this.running = false; - await this.blockStream.stop(); - this.log.info('Stopped'); - } - - /** Triggers a single run. */ - public async trigger() { await this.blockStream.sync(); } - private async getSynchedBlockNumber() { + public async getSynchedBlockNumber() { return (await this.db.getBlockNumber()) ?? this.initialSyncBlockNumber; } - - /** - * Checks whether all the blocks were processed (tree roots updated, txs updated with block info, etc.). - * @returns True if there are no outstanding blocks to be synched. - * @remarks This indicates that blocks and transactions are synched even if notes are not. - * @remarks Compares local block number with the block number from aztec node. - */ - public async isGlobalStateSynchronized() { - const latest = await this.node.getBlockNumber(); - return latest <= (await this.getSynchedBlockNumber()); - } - - /** - * Returns the latest block that has been synchronized by the synchronizer and each account. - * @returns The latest block synchronized for blocks, and the latest block synched for notes for each public key being tracked. - */ - public async getSyncStatus() { - const lastBlockNumber = await this.getSynchedBlockNumber(); - return { - blocks: lastBlockNumber, - }; - } } diff --git a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts b/yarn-project/pxe/src/utils/create_pxe_service.ts similarity index 93% rename from yarn-project/pxe/src/pxe_service/create_pxe_service.ts rename to yarn-project/pxe/src/utils/create_pxe_service.ts index bd168463788..773c7fa08aa 100644 --- a/yarn-project/pxe/src/pxe_service/create_pxe_service.ts +++ b/yarn-project/pxe/src/utils/create_pxe_service.ts @@ -9,7 +9,7 @@ import { L2TipsStore } from '@aztec/kv-store/stores'; import { type PXEServiceConfig } from '../config/index.js'; import { KVPxeDatabase } from '../database/kv_pxe_database.js'; import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js'; -import { PXEService } from './pxe_service.js'; +import { PXEService } from '../pxe_service/pxe_service.js'; /** * Create and start an PXEService instance with the given AztecNode. @@ -47,9 +47,9 @@ export async function createPXEService( const tips = new L2TipsStore(store, 'pxe'); const prover = proofCreator ?? (await createProver(config, logSuffix)); - const server = new PXEService(keyStore, aztecNode, db, tips, prover, config, logSuffix); - await server.start(); - return server; + const pxe = new PXEService(keyStore, aztecNode, db, tips, prover, config, logSuffix); + await pxe.init(); + return pxe; } function createProver(config: PXEServiceConfig, logSuffix?: string) { diff --git a/yarn-project/pxe/src/utils/index.ts b/yarn-project/pxe/src/utils/index.ts deleted file mode 100644 index f971258aca0..00000000000 --- a/yarn-project/pxe/src/utils/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -import { BBNativePrivateKernelProver } from '@aztec/bb-prover'; -import { type AztecNode, type PrivateKernelProver } from '@aztec/circuit-types'; -import { randomBytes } from '@aztec/foundation/crypto'; -import { createLogger } from '@aztec/foundation/log'; -import { KeyStore } from '@aztec/key-store'; -import { createStore } from '@aztec/kv-store/lmdb'; -import { L2TipsStore } from '@aztec/kv-store/stores'; - -import { type PXEServiceConfig } from '../config/index.js'; -import { KVPxeDatabase } from '../database/kv_pxe_database.js'; -import { TestPrivateKernelProver } from '../kernel_prover/test/test_circuit_prover.js'; -import { PXEService } from '../pxe_service/pxe_service.js'; - -/** - * Create and start an PXEService instance with the given AztecNode. - * If no keyStore or database is provided, it will use KeyStore and MemoryDB as default values. - * Returns a Promise that resolves to the started PXEService instance. - * - * @param aztecNode - The AztecNode instance to be used by the server. - * @param config - The PXE Service Config to use - * @param options - (Optional) Optional information for creating an PXEService. - * @param proofCreator - An optional proof creator to use in place of any other configuration - * @returns A Promise that resolves to the started PXEService instance. - */ -export async function createPXEService( - aztecNode: AztecNode, - config: PXEServiceConfig, - useLogSuffix: string | boolean | undefined = undefined, - proofCreator?: PrivateKernelProver, -) { - const logSuffix = - typeof useLogSuffix === 'boolean' ? (useLogSuffix ? randomBytes(3).toString('hex') : undefined) : useLogSuffix; - - const l1Contracts = await aztecNode.getL1ContractAddresses(); - const configWithContracts = { - ...config, - l1Contracts, - } as PXEServiceConfig; - - const keyStore = new KeyStore( - await createStore('pxe_key_store', configWithContracts, createLogger('pxe:keystore:lmdb')), - ); - - const store = await createStore('pxe_data', configWithContracts, createLogger('pxe:data:lmdb')); - - const db = await KVPxeDatabase.create(store); - const tips = new L2TipsStore(store, 'pxe'); - - const prover = proofCreator ?? (await createProver(config, logSuffix)); - const server = new PXEService(keyStore, aztecNode, db, tips, prover, config, logSuffix); - await server.start(); - return server; -} - -function createProver(config: PXEServiceConfig, logSuffix?: string) { - if (!config.proverEnabled) { - return new TestPrivateKernelProver(); - } - - // (@PhilWindle) Temporary validation until WASM is implemented - if (!config.bbBinaryPath || !config.bbWorkingDirectory) { - throw new Error(`Prover must be configured with binary path and working directory`); - } - const bbConfig = config as Required> & PXEServiceConfig; - const log = createLogger('pxe:bb-native-prover' + (logSuffix ? `:${logSuffix}` : '')); - return BBNativePrivateKernelProver.new({ bbSkipCleanup: false, ...bbConfig }, log); -}