@aztec/aztec-node 5.0.0-nightly.20260707 → 5.0.0-nightly.20260709

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dest/factory.d.ts CHANGED
@@ -30,4 +30,4 @@ export interface CreateAztecNodeOptions {
30
30
  * @returns A fully synced Aztec Node for use in development/testing.
31
31
  */
32
32
  export declare function createAztecNodeService(inputConfig: AztecNodeConfig, deps?: CreateAztecNodeDeps, options?: CreateAztecNodeOptions): Promise<AztecNodeService>;
33
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBWUEsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUl2RCxPQUFPLEVBQUUsS0FBSyxhQUFhLEVBQW1CLE1BQU0sWUFBWSxDQUFDO0FBQ2pFLE9BQU8sRUFBbUIsS0FBSyxjQUFjLEVBQW9CLE1BQU0sb0JBQW9CLENBQUM7QUFFNUYsT0FBTyxFQUlMLEtBQUssa0JBQWtCLEVBQ3hCLE1BQU0seUJBQXlCLENBQUM7QUFnQmpDLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdELE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBc0IsTUFBTSx5QkFBeUIsQ0FBQztBQVVuRixPQUFPLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBS25GLE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBOEIsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUcxRCxvR0FBb0c7QUFDcEcsTUFBTSxXQUFXLG1CQUFtQjtJQUNsQyxTQUFTLENBQUMsRUFBRSxlQUFlLENBQUM7SUFDNUIsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLFNBQVMsQ0FBQyxFQUFFLGtCQUFrQixDQUFDO0lBQy9CLFlBQVksQ0FBQyxFQUFFLFlBQVksQ0FBQztJQUM1QixhQUFhLENBQUMsRUFBRSxhQUFhLENBQUM7SUFDOUIsY0FBYyxDQUFDLEVBQUUsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQ3pDLG9CQUFvQixDQUFDLEVBQUUsMEJBQTBCLENBQUM7Q0FDbkQ7QUFFRCw2RUFBNkU7QUFDN0UsTUFBTSxXQUFXLHNCQUFzQjtJQUNyQyxPQUFPLENBQUMsRUFBRSxXQUFXLENBQUM7SUFDdEIsa0JBQWtCLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDN0IsbUJBQW1CLENBQUMsRUFBRSxPQUFPLENBQUM7Q0FDL0I7QUFFRDs7OztHQUlHO0FBQ0gsd0JBQXNCLHNCQUFzQixDQUMxQyxXQUFXLEVBQUUsZUFBZSxFQUM1QixJQUFJLEdBQUUsbUJBQXdCLEVBQzlCLE9BQU8sR0FBRSxzQkFBMkIsR0FDbkMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBNmhCM0IifQ==
33
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBWUEsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUl2RCxPQUFPLEVBQUUsS0FBSyxhQUFhLEVBQW1CLE1BQU0sWUFBWSxDQUFDO0FBQ2pFLE9BQU8sRUFBbUIsS0FBSyxjQUFjLEVBQW9CLE1BQU0sb0JBQW9CLENBQUM7QUFFNUYsT0FBTyxFQUlMLEtBQUssa0JBQWtCLEVBQ3hCLE1BQU0seUJBQXlCLENBQUM7QUFnQmpDLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdELE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBc0IsTUFBTSx5QkFBeUIsQ0FBQztBQVVuRixPQUFPLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxNQUFNLGtDQUFrQyxDQUFDO0FBS25GLE9BQU8sRUFBRSxLQUFLLGVBQWUsRUFBOEIsTUFBTSx3QkFBd0IsQ0FBQztBQUMxRixPQUFPLEVBQUUsZ0JBQWdCLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQUcxRCxvR0FBb0c7QUFDcEcsTUFBTSxXQUFXLG1CQUFtQjtJQUNsQyxTQUFTLENBQUMsRUFBRSxlQUFlLENBQUM7SUFDNUIsTUFBTSxDQUFDLEVBQUUsTUFBTSxDQUFDO0lBQ2hCLFNBQVMsQ0FBQyxFQUFFLGtCQUFrQixDQUFDO0lBQy9CLFlBQVksQ0FBQyxFQUFFLFlBQVksQ0FBQztJQUM1QixhQUFhLENBQUMsRUFBRSxhQUFhLENBQUM7SUFDOUIsY0FBYyxDQUFDLEVBQUUsT0FBTyxDQUFDLGNBQWMsQ0FBQyxDQUFDO0lBQ3pDLG9CQUFvQixDQUFDLEVBQUUsMEJBQTBCLENBQUM7Q0FDbkQ7QUFFRCw2RUFBNkU7QUFDN0UsTUFBTSxXQUFXLHNCQUFzQjtJQUNyQyxPQUFPLENBQUMsRUFBRSxXQUFXLENBQUM7SUFDdEIsa0JBQWtCLENBQUMsRUFBRSxPQUFPLENBQUM7SUFDN0IsbUJBQW1CLENBQUMsRUFBRSxPQUFPLENBQUM7Q0FDL0I7QUFFRDs7OztHQUlHO0FBQ0gsd0JBQXNCLHNCQUFzQixDQUMxQyxXQUFXLEVBQUUsZUFBZSxFQUM1QixJQUFJLEdBQUUsbUJBQXdCLEVBQzlCLE9BQU8sR0FBRSxzQkFBMkIsR0FDbkMsT0FBTyxDQUFDLGdCQUFnQixDQUFDLENBOGlCM0IifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIvD,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAmB,KAAK,cAAc,EAAoB,MAAM,oBAAoB,CAAC;AAE5F,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAgBjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAUnF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAKnF,OAAO,EAAE,KAAK,eAAe,EAA8B,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,oGAAoG;AACpG,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;CACnD;AAED,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,eAAe,EAC5B,IAAI,GAAE,mBAAwB,EAC9B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CA6hB3B"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAIvD,OAAO,EAAE,KAAK,aAAa,EAAmB,MAAM,YAAY,CAAC;AACjE,OAAO,EAAmB,KAAK,cAAc,EAAoB,MAAM,oBAAoB,CAAC;AAE5F,OAAO,EAIL,KAAK,kBAAkB,EACxB,MAAM,yBAAyB,CAAC;AAgBjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,2BAA2B,CAAC;AAC7D,OAAO,EAAE,KAAK,eAAe,EAAsB,MAAM,yBAAyB,CAAC;AAUnF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAKnF,OAAO,EAAE,KAAK,eAAe,EAA8B,MAAM,wBAAwB,CAAC;AAC1F,OAAO,EAAE,gBAAgB,EAAE,MAAM,wBAAwB,CAAC;AAG1D,oGAAoG;AACpG,MAAM,WAAW,mBAAmB;IAClC,SAAS,CAAC,EAAE,eAAe,CAAC;IAC5B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,SAAS,CAAC,EAAE,kBAAkB,CAAC;IAC/B,YAAY,CAAC,EAAE,YAAY,CAAC;IAC5B,aAAa,CAAC,EAAE,aAAa,CAAC;IAC9B,cAAc,CAAC,EAAE,OAAO,CAAC,cAAc,CAAC,CAAC;IACzC,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;CACnD;AAED,6EAA6E;AAC7E,MAAM,WAAW,sBAAsB;IACrC,OAAO,CAAC,EAAE,WAAW,CAAC;IACtB,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,mBAAmB,CAAC,EAAE,OAAO,CAAC;CAC/B;AAED;;;;GAIG;AACH,wBAAsB,sBAAsB,CAC1C,WAAW,EAAE,eAAe,EAC5B,IAAI,GAAE,mBAAwB,EAC9B,OAAO,GAAE,sBAA2B,GACnC,OAAO,CAAC,gBAAgB,CAAC,CA8iB3B"}
package/dest/factory.js CHANGED
@@ -166,6 +166,19 @@ import { createSentinel } from './sentinel/factory.js';
166
166
  const globalVariableBuilder = new GlobalVariableBuilder(publicClient, globalVariableBuilderConfig);
167
167
  const feeProvider = new FeeProviderImpl(dateProvider, publicClient, globalVariableBuilderConfig);
168
168
  const collectOffenses = !config.disableValidator || config.enableOffenseCollection;
169
+ // A prover node may still be proving an epoch whose blocks have already finalized on L1. Its proof
170
+ // submission window spans (proofSubmissionEpochs + 1) epochs, so its tx pool must keep finalized txs
171
+ // for at least that long to re-fetch them for proving and failure upload. Operators may configure a
172
+ // larger margin but not a smaller one.
173
+ if (config.enableProverNode) {
174
+ const proofSubmissionEpochs = await rollupContract.getProofSubmissionEpochs();
175
+ const proverRetentionFloorSlots = (proofSubmissionEpochs + 1) * Number(epochDuration);
176
+ const configuredSlots = config.keepFinalizedTxsForSlots ?? 0;
177
+ if (proverRetentionFloorSlots > configuredSlots) {
178
+ log.warn(`Increasing keepFinalizedTxsForSlots from ${configuredSlots} to ${proverRetentionFloorSlots} ` + `(proof submission window of ${proofSubmissionEpochs + 1} epochs) to retain finalized txs for proving`);
179
+ config.keepFinalizedTxsForSlots = proverRetentionFloorSlots;
180
+ }
181
+ }
169
182
  // create the tx pool and the p2p client, which will need the l2 block source
170
183
  const p2pClient = await createP2PClient(config, archiver, peerProofVerifier, worldStateSynchronizer, epochCache, feeProvider, packageVersion, dateProvider, telemetry, deps.p2pClientDeps, initialBlockHash);
171
184
  started.push(p2pClient);
@@ -1,5 +1,5 @@
1
1
  import { ARCHIVE_HEIGHT, type L1_TO_L2_MSG_TREE_HEIGHT, type NOTE_HASH_TREE_HEIGHT } from '@aztec/constants';
2
- import { BlockNumber, type CheckpointNumber, type EpochNumber } from '@aztec/foundation/branded-types';
2
+ import { type CheckpointNumber, type EpochNumber } from '@aztec/foundation/branded-types';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
4
  import { type Logger } from '@aztec/foundation/log';
5
5
  import { MembershipWitness, type SiblingPath } from '@aztec/foundation/trees';
@@ -50,12 +50,16 @@ export declare class NodeWorldStateQueries {
50
50
  getPublicDataWitness(referenceBlock: BlockParameter, leafSlot: Fr): Promise<PublicDataWitness | undefined>;
51
51
  getPublicStorageAt(referenceBlock: BlockParameter, contract: AztecAddress, slot: Fr): Promise<Fr>;
52
52
  /**
53
- * Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
54
- * @param block - The block parameter (block number, block hash, or 'latest') at which to get the data.
53
+ * Returns an instance of MerkleTreeOperations having first ensured the world state is synced to the requested
54
+ * block on the correct fork. Every query variant is resolved to a concrete (block number, block hash), which is
55
+ * threaded through both the sync and the snapshot read so a reorg that replaced the block at that height is
56
+ * detected rather than served silently. Transient failures — a prune landing between resolution and sync, or a
57
+ * fork flip caught at either the sync or the snapshot stage — are retried a few times, re-resolving the query
58
+ * against the updated chain each time; terminal failures — an unknown block hash at resolution, or a block whose
59
+ * history world state has pruned away — are thrown immediately.
60
+ * @param block - The block parameter (block number, block hash, or tag) at which to get the data.
55
61
  * @returns An instance of a committed MerkleTreeOperations
56
62
  */
57
- getWorldState(block: BlockParameter): Promise<import("@aztec/stdlib/trees").MerkleTreeReadOperations>;
58
- /** Resolves any {@link BlockParameter} variant to a concrete block number. */
59
- resolveBlockNumber(block: BlockParameter): Promise<BlockNumber>;
63
+ getWorldState(block: BlockParameter): Promise<import("@aztec/world-state").MerkleTreeReadOperations>;
60
64
  }
61
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV93b3JsZF9zdGF0ZV9xdWVyaWVzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kdWxlcy9ub2RlX3dvcmxkX3N0YXRlX3F1ZXJpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxLQUFLLHdCQUF3QixFQUFFLEtBQUsscUJBQXFCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3RyxPQUFPLEVBQUUsV0FBVyxFQUFFLEtBQUssZ0JBQWdCLEVBQUUsS0FBSyxXQUFXLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUV2RyxPQUFPLEVBQUUsRUFBRSxFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDcEQsT0FBTyxFQUFFLEtBQUssTUFBTSxFQUFnQixNQUFNLHVCQUF1QixDQUFDO0FBQ2xFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxLQUFLLFdBQVcsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzlFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBQ2hFLE9BQU8sRUFDTCxLQUFLLFNBQVMsRUFDZCxLQUFLLGNBQWMsRUFDbkIsS0FBSyxXQUFXLEVBQ2hCLEtBQUssYUFBYSxFQUVuQixNQUFNLHFCQUFxQixDQUFDO0FBRTdCLE9BQU8sS0FBSyxFQUFFLHNCQUFzQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDOUUsT0FBTyxFQUFhLEtBQUssbUJBQW1CLEVBQUUsS0FBSyx1QkFBdUIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBQzVHLE9BQU8sRUFDTCxZQUFZLEVBRVosMEJBQTBCLEVBRTFCLGlCQUFpQixFQUNsQixNQUFNLHFCQUFxQixDQUFDO0FBQzdCLE9BQU8sS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLGtCQUFrQixDQUFDO0FBSS9DLHNFQUFzRTtBQUN0RSxNQUFNLFdBQVcseUJBQXlCO0lBQ3hDLHNCQUFzQixFQUFFLHNCQUFzQixDQUFDO0lB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
65
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm9kZV93b3JsZF9zdGF0ZV9xdWVyaWVzLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvbW9kdWxlcy9ub2RlX3dvcmxkX3N0YXRlX3F1ZXJpZXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLGNBQWMsRUFBRSxLQUFLLHdCQUF3QixFQUFFLEtBQUsscUJBQXFCLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQUM3RyxPQUFPLEVBQWUsS0FBSyxnQkFBZ0IsRUFBRSxLQUFLLFdBQVcsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBRXZHLE9BQU8sRUFBRSxFQUFFLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQztBQUNwRCxPQUFPLEVBQUUsS0FBSyxNQUFNLEVBQWdCLE1BQU0sdUJBQXVCLENBQUM7QUFFbEUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLEtBQUssV0FBVyxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDOUUsT0FBTyxLQUFLLEVBQUUsWUFBWSxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFDaEUsT0FBTyxFQUNMLEtBQUssU0FBUyxFQUNkLEtBQUssY0FBYyxFQUNuQixLQUFLLFdBQVcsRUFDaEIsS0FBSyxhQUFhLEVBR25CLE1BQU0scUJBQXFCLENBQUM7QUFFN0IsT0FBTyxLQUFLLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUM5RSxPQUFPLEVBQWEsS0FBSyxtQkFBbUIsRUFBRSxLQUFLLHVCQUF1QixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDNUcsT0FBTyxFQUNMLFlBQVksRUFFWiwwQkFBMEIsRUFFMUIsaUJBQWlCLEVBQ2xCLE1BQU0scUJBQXFCLENBQUM7QUFDN0IsT0FBTyxLQUFLLEVBQUUsTUFBTSxFQUFFLE1BQU0sa0JBQWtCLENBQUM7QUFXL0Msc0VBQXNFO0FBQ3RFLE1BQU0sV0FBVyx5QkFBeUI7SUFDeEMsc0JBQXNCLEVBQUUsc0JBQXNCLENBQUM7SUFDL0MsV0FBVyxF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
@@ -1 +1 @@
1
- {"version":3,"file":"node_world_state_queries.d.ts","sourceRoot":"","sources":["../../src/modules/node_world_state_queries.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,KAAK,wBAAwB,EAAE,KAAK,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC7G,OAAO,EAAE,WAAW,EAAE,KAAK,gBAAgB,EAAE,KAAK,WAAW,EAAE,MAAM,iCAAiC,CAAC;AAEvG,OAAO,EAAE,EAAE,EAAE,MAAM,gCAAgC,CAAC;AACpD,OAAO,EAAE,KAAK,MAAM,EAAgB,MAAM,uBAAuB,CAAC;AAClE,OAAO,EAAE,iBAAiB,EAAE,KAAK,WAAW,EAAE,MAAM,yBAAyB,CAAC;AAC9E,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,6BAA6B,CAAC;AAChE,OAAO,EACL,KAAK,SAAS,EACd,KAAK,cAAc,EACnB,KAAK,WAAW,EAChB,KAAK,aAAa,EAEnB,MAAM,qBAAqB,CAAC;AAE7B,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AAC9E,OAAO,EAAa,KAAK,mBAAmB,EAAE,KAAK,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAC5G,OAAO,EACL,YAAY,EAEZ,0BAA0B,EAE1B,iBAAiB,EAClB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAI/C,sEAAsE;AACtE,MAAM,WAAW,yBAAyB;IACxC,sBAAsB,EAAE,sBAAsB,CAAC;IAC/C,WAAW,EAAE,aAAa,CAAC;IAC3B,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,GAAG,CAAC,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,qBAAa,qBAAqB;;IAChC,OAAO,CAAC,QAAQ,CAAC,sBAAsB,CAAyB;IAChE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAgB;IAC5C,OAAO,CAAC,QAAQ,CAAC,mBAAmB,CAAsB;IAC1D,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAS;IAE7B,YAAY,IAAI,EAAE,yBAAyB,EAK1C;IAEY,iBAAiB,CAC5B,cAAc,EAAE,cAAc,EAC9B,MAAM,EAAE,YAAY,EACpB,UAAU,EAAE,EAAE,EAAE,GACf,OAAO,CAAC,CAAC,WAAW,CAAC,MAAM,CAAC,GAAG,SAAS,CAAC,EAAE,CAAC,CA+D9C;IAEY,6BAA6B,CACxC,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,SAAS,GACnB,OAAO,CAAC,iBAAiB,CAAC,OAAO,cAAc,CAAC,GAAG,SAAS,CAAC,CAc/D;IAEY,4BAA4B,CACvC,cAAc,EAAE,cAAc,EAC9B,QAAQ,EAAE,EAAE,GACX,OAAO,CAAC,iBAAiB,CAAC,OAAO,qBAAqB,CAAC,GAAG,SAAS,CAAC,CAStE;IAEY,iCAAiC,CAC5C,cAAc,EAAE,cAAc,EAC9B,aAAa,EAAE,EAAE,GAChB,OAAO,CAAC,CAAC,MAAM,EAAE,WAAW,CAAC,OAAO,wBAAwB,CAAC,CAAC,GAAG,SAAS,CAAC,CAS7E;IAEY,0BAA0B,CAAC,aAAa,EAAE,EAAE,GAAG,OAAO,CAAC,gBAAgB,GAAG,SAAS,CAAC,CAGhG;IAED;;;;;OAKG;IACU,iBAAiB,CAAC,KAAK,EAAE,WAAW,GAAG,OAAO,CAAC,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAMtE;IAED;;;OAGG;IACI,0BAA0B,CAC/B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,EAAE,EACX,gBAAgB,CAAC,EAAE,MAAM,GACxB,OAAO,CAAC,uBAAuB,GAAG,SAAS,CAAC,CAE9C;IAEY,6BAA6B,CACxC,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,EAAE,GACZ,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAcjD;IAEY,gCAAgC,CAC3C,cAAc,EAAE,cAAc,EAC9B,SAAS,EAAE,EAAE,GACZ,OAAO,CAAC,0BAA0B,GAAG,SAAS,CAAC,CAgBjD;IAEK,oBAAoB,CAAC,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,EAAE,GAAG,OAAO,CAAC,iBAAiB,GAAG,SAAS,CAAC,CAa/G;IAEY,kBAAkB,CAAC,cAAc,EAAE,cAAc,EAAE,QAAQ,EAAE,YAAY,EAAE,IAAI,EAAE,EAAE,GAAG,OAAO,CAAC,EAAE,CAAC,CAa7G;IAED;;;;OAIG;IACU,aAAa,CAAC,KAAK,EAAE,cAAc,mEAoD/C;IAED,8EAA8E;IACjE,kBAAkB,CAAC,KAAK,EAAE,cAAc,GAAG,OAAO,CAAC,WAAW,CAAC,CAe3E;CAaF"}
1
+ {"version":3,"file":"node_world_state_queries.d.ts","sourceRoot":"","sources":["../../src/modules/node_world_state_queries.ts"],"names":[],"mappings":"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"}
@@ -2,12 +2,16 @@ import { BlockNumber } from '@aztec/foundation/branded-types';
2
2
  import { chunkBy } from '@aztec/foundation/collection';
3
3
  import { Fr } from '@aztec/foundation/curves/bn254';
4
4
  import { createLogger } from '@aztec/foundation/log';
5
+ import { sleep } from '@aztec/foundation/sleep';
5
6
  import { MembershipWitness } from '@aztec/foundation/trees';
6
7
  import { inspectBlockParameter } from '@aztec/stdlib/block';
7
8
  import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
8
9
  import { InboxLeaf } from '@aztec/stdlib/messaging';
9
10
  import { MerkleTreeId, NullifierMembershipWitness, PublicDataWitness } from '@aztec/stdlib/trees';
11
+ import { WorldStateSynchronizerError } from '@aztec/world-state';
10
12
  import { normalizeBlockParameter } from './block_parameter.js';
13
+ /** Attempts at resolving a query and syncing world state to it before giving up (see {@link NodeWorldStateQueries.getWorldState}). */ const WORLD_STATE_SYNC_ATTEMPTS = 3;
14
+ /** Delay between world-state sync attempts. */ const WORLD_STATE_SYNC_RETRY_DELAY_MS = 100;
11
15
  /**
12
16
  * Serves the node's Merkle-tree and membership-witness queries against committed world-state at a
13
17
  * requested block. Extracted from `AztecNodeService` so the block-resolution and reorg-aware sync logic
@@ -80,7 +84,7 @@ import { normalizeBlockParameter } from './block_parameter.js';
80
84
  // The Noir circuit checks the archive membership proof against `anchor_block_header.last_archive.root`,
81
85
  // which is the archive tree root BEFORE the anchor block was added (i.e. the state after block N-1).
82
86
  // So we need the world state at block N-1, not block N, to produce a sibling path matching that root.
83
- const referenceBlockNumber = await this.resolveBlockNumber(referenceBlock);
87
+ const referenceBlockNumber = await this.#resolveBlockNumber(referenceBlock);
84
88
  if (referenceBlockNumber === BlockNumber.ZERO) {
85
89
  // Block 0 (the initial block) has an empty archive, so no membership witness can exist.
86
90
  return undefined;
@@ -186,72 +190,83 @@ import { normalizeBlockParameter } from './block_parameter.js';
186
190
  return preimage.leaf.value;
187
191
  }
188
192
  /**
189
- * Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
190
- * @param block - The block parameter (block number, block hash, or 'latest') at which to get the data.
193
+ * Returns an instance of MerkleTreeOperations having first ensured the world state is synced to the requested
194
+ * block on the correct fork. Every query variant is resolved to a concrete (block number, block hash), which is
195
+ * threaded through both the sync and the snapshot read so a reorg that replaced the block at that height is
196
+ * detected rather than served silently. Transient failures — a prune landing between resolution and sync, or a
197
+ * fork flip caught at either the sync or the snapshot stage — are retried a few times, re-resolving the query
198
+ * against the updated chain each time; terminal failures — an unknown block hash at resolution, or a block whose
199
+ * history world state has pruned away — are thrown immediately.
200
+ * @param block - The block parameter (block number, block hash, or tag) at which to get the data.
191
201
  * @returns An instance of a committed MerkleTreeOperations
192
202
  */ async getWorldState(block) {
193
203
  const query = normalizeBlockParameter(block);
194
- // When the request anchors on a specific block hash, resolve it against the archiver up front and
195
- // drive the world-state sync to that exact block number and hash. Resolving against the archiver
196
- // first fails fast with a clear reorg error if the hash is unknown, and passing the hash to the
197
- // synchronizer makes the sync reorg-aware: it barriers until the archive-tree commit for that block
198
- // has landed and verifies it matches the requested fork, instead of syncing to bare latest height
199
- // and then racing the snapshot read below against an in-flight archive-tree write.
200
- const requestedHash = 'hash' in query ? query.hash : undefined;
201
- const anchorBlockNumber = requestedHash !== undefined ? await this.resolveBlockNumber(query) : undefined;
202
- let blockSyncedTo = BlockNumber.ZERO;
203
- try {
204
- // Attempt to sync the world state if necessary
205
- blockSyncedTo = await this.#syncWorldState(anchorBlockNumber, requestedHash);
206
- } catch (err) {
207
- this.log.error(`Error getting world state: ${err}`);
204
+ for(let attempt = 1;; attempt++){
205
+ try {
206
+ return await this.#resolveWorldState(query);
207
+ } catch (err) {
208
+ if (attempt >= WORLD_STATE_SYNC_ATTEMPTS || !(err instanceof WorldStateSynchronizerError)) {
209
+ throw err;
210
+ }
211
+ this.log.verbose(`Retrying world state query after sync failure: ${err.message}`, {
212
+ attempt,
213
+ block: inspectBlockParameter(block)
214
+ });
215
+ await sleep(WORLD_STATE_SYNC_RETRY_DELAY_MS);
216
+ }
208
217
  }
218
+ }
219
+ /**
220
+ * Resolves `query` to a concrete (block number, block hash), syncs world state to that exact fork, and returns
221
+ * the committed db (for `proposed` queries) or the fork-verified snapshot at the resolved block.
222
+ */ async #resolveWorldState(query) {
223
+ // User requests 'latest on the current fork', so the committed db is returned unverified
209
224
  if ('tag' in query && query.tag === 'proposed') {
210
- this.log.debug(`Using committed db for latest block, world state synced upto ${blockSyncedTo}`);
225
+ this.log.debug(`Using committed db for latest block`);
226
+ await this.worldStateSynchronizer.syncImmediate();
211
227
  return this.worldStateSynchronizer.getCommitted();
212
228
  }
213
- const blockNumber = anchorBlockNumber ?? await this.resolveBlockNumber(query);
214
- // Check it's within world state sync range
215
- if (blockNumber > blockSyncedTo) {
216
- throw new Error(`Queried block ${inspectBlockParameter(block)} not yet synced by the node (node is synced upto ${blockSyncedTo}).`);
217
- }
218
- this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
219
- const snapshot = this.worldStateSynchronizer.getSnapshot(blockNumber);
220
- // Double-check world-state synced to the same block hash as was requested.
221
- // Block 0 is skipped: the snapshot returned by `getSnapshot(0)` is the *pre*-genesis archive
222
- // (size 0), so leaf 0 is not yet inserted from that snapshot's view even though block 0's hash
223
- // does live at archive index 0 in the committed tree. The genesis hash is already validated by
224
- // the archiver when it resolves the hash query to block number 0.
225
- if (requestedHash !== undefined && blockNumber !== BlockNumber.ZERO) {
226
- const blockHash = await snapshot.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
227
- if (!blockHash || !requestedHash.equals(blockHash)) {
228
- throw new Error(`Block hash ${requestedHash.toString()} not found in world state at block number ${blockNumber} (world state has ${blockHash?.toString() ?? 'no hash'} at that index, genesis header hash is ${this.blockSource.getGenesisBlockHash().toString()}). If the node API has been queried with anchor block hash possibly a reorg has occurred.`);
229
- }
229
+ // Resolve the query against the block source BEFORE syncing to a concrete (number, hash), and drive the sync to
230
+ // that exact fork. Resolving after the sync races the block source: the resolved tip can advance past what world
231
+ // state synced while the sync is in flight. Passing the hash makes the sync reorg-aware — it barriers until the
232
+ // archive-tree commit for that block has landed and verifies it matches the requested fork, throwing otherwise.
233
+ const { blockNumber, blockHash } = await this.#resolveBlockNumberAndHash(query);
234
+ const blockSyncedTo = await this.worldStateSynchronizer.syncImmediate(blockNumber, blockHash);
235
+ // The fork could flip between it returning and the snapshot being read, so getVerifiedSnapshot pins the
236
+ // returned view to the resolved fork (re-resolved by the retry loop on mismatch).
237
+ this.log.debug(`Using verified snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
238
+ return await this.worldStateSynchronizer.getVerifiedSnapshot(blockNumber, blockHash);
239
+ }
240
+ /** Resolves any {@link BlockParameter} variant to its concrete `(blockNumber, blockHash)` via the block source. */ async #resolveBlockNumberAndHash(query) {
241
+ const blockData = await this.blockSource.getBlockData(query);
242
+ if (blockData === undefined) {
243
+ this.#throwOnUndefinedBlockData(query);
230
244
  }
231
- return snapshot;
245
+ return {
246
+ blockNumber: blockData.header.getBlockNumber(),
247
+ blockHash: blockData.blockHash
248
+ };
232
249
  }
233
- /** Resolves any {@link BlockParameter} variant to a concrete block number. */ async resolveBlockNumber(block) {
234
- const query = normalizeBlockParameter(block);
235
- const blockNumber = await this.blockSource.getBlockNumber(query);
250
+ /** Resolves any {@link BlockParameter} variant to a concrete block number. */ async #resolveBlockNumber(block) {
251
+ const blockQuery = normalizeBlockParameter(block);
252
+ const blockNumber = await this.blockSource.getBlockNumber(blockQuery);
236
253
  if (blockNumber === undefined) {
237
- if ('hash' in query) {
238
- throw new Error(`Block hash ${query.hash.toString()} not found when querying world state. If the node API has been queried with anchor block hash possibly a reorg has occurred.`);
239
- }
240
- if ('archive' in query) {
241
- throw new Error(`Block with archive ${query.archive.toString()} not found.`);
242
- }
243
- throw new Error(`Block not found for ${inspectBlockParameter(block)}.`);
254
+ this.#throwOnUndefinedBlockData(blockQuery);
244
255
  }
245
256
  return blockNumber;
246
257
  }
247
258
  /**
248
- * Ensure the world state is synced.
249
- * @param targetBlockNumber - Block to sync up to. Defaults to the latest block known to the archiver.
250
- * @param blockHash - If provided, the synchronizer verifies the block at `targetBlockNumber` matches this
251
- * hash, resyncing (and so detecting reorgs) if it does not yet match or has been reorged away.
252
- * @returns A promise that fulfils once the world state is synced
253
- */ async #syncWorldState(targetBlockNumber, blockHash) {
254
- const target = targetBlockNumber ?? await this.blockSource.getBlockNumber();
255
- return await this.worldStateSynchronizer.syncImmediate(target, blockHash);
259
+ * Hash and archive misses are terminal (an unknown block, likely a reorg); tag and number misses are transient —
260
+ * the block may have been pruned between the tag->number resolution and this data read, or may simply not have
261
+ * arrived yet and surface as {@link WorldStateSynchronizerError} so the retry loop re-resolves against the
262
+ * current chain.
263
+ */ #throwOnUndefinedBlockData(query) {
264
+ if ('hash' in query) {
265
+ throw new Error(`Block hash ${query.hash.toString()} not found when resolving query. If the node API has been queried with anchor block hash possibly a reorg has occurred.`);
266
+ }
267
+ if ('archive' in query) {
268
+ throw new Error(`Block with archive ${query.archive.toString()} not found when resolving query.`);
269
+ }
270
+ throw new WorldStateSynchronizerError(`Block not found for ${inspectBlockParameter(query)} when resolving query.`);
256
271
  }
257
272
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/aztec-node",
3
- "version": "5.0.0-nightly.20260707",
3
+ "version": "5.0.0-nightly.20260709",
4
4
  "main": "dest/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -65,33 +65,33 @@
65
65
  ]
66
66
  },
67
67
  "dependencies": {
68
- "@aztec/archiver": "5.0.0-nightly.20260707",
69
- "@aztec/bb-prover": "5.0.0-nightly.20260707",
70
- "@aztec/bb.js": "5.0.0-nightly.20260707",
71
- "@aztec/blob-client": "5.0.0-nightly.20260707",
72
- "@aztec/blob-lib": "5.0.0-nightly.20260707",
73
- "@aztec/constants": "5.0.0-nightly.20260707",
74
- "@aztec/epoch-cache": "5.0.0-nightly.20260707",
75
- "@aztec/ethereum": "5.0.0-nightly.20260707",
76
- "@aztec/foundation": "5.0.0-nightly.20260707",
77
- "@aztec/kv-store": "5.0.0-nightly.20260707",
78
- "@aztec/l1-artifacts": "5.0.0-nightly.20260707",
79
- "@aztec/node-keystore": "5.0.0-nightly.20260707",
80
- "@aztec/node-lib": "5.0.0-nightly.20260707",
81
- "@aztec/noir-protocol-circuits-types": "5.0.0-nightly.20260707",
82
- "@aztec/p2p": "5.0.0-nightly.20260707",
83
- "@aztec/protocol-contracts": "5.0.0-nightly.20260707",
84
- "@aztec/prover-client": "5.0.0-nightly.20260707",
85
- "@aztec/prover-node": "5.0.0-nightly.20260707",
86
- "@aztec/sequencer-client": "5.0.0-nightly.20260707",
87
- "@aztec/simulator": "5.0.0-nightly.20260707",
88
- "@aztec/slasher": "5.0.0-nightly.20260707",
89
- "@aztec/standard-contracts": "5.0.0-nightly.20260707",
90
- "@aztec/stdlib": "5.0.0-nightly.20260707",
91
- "@aztec/telemetry-client": "5.0.0-nightly.20260707",
92
- "@aztec/validator-client": "5.0.0-nightly.20260707",
93
- "@aztec/validator-ha-signer": "5.0.0-nightly.20260707",
94
- "@aztec/world-state": "5.0.0-nightly.20260707",
68
+ "@aztec/archiver": "5.0.0-nightly.20260709",
69
+ "@aztec/bb-prover": "5.0.0-nightly.20260709",
70
+ "@aztec/bb.js": "5.0.0-nightly.20260709",
71
+ "@aztec/blob-client": "5.0.0-nightly.20260709",
72
+ "@aztec/blob-lib": "5.0.0-nightly.20260709",
73
+ "@aztec/constants": "5.0.0-nightly.20260709",
74
+ "@aztec/epoch-cache": "5.0.0-nightly.20260709",
75
+ "@aztec/ethereum": "5.0.0-nightly.20260709",
76
+ "@aztec/foundation": "5.0.0-nightly.20260709",
77
+ "@aztec/kv-store": "5.0.0-nightly.20260709",
78
+ "@aztec/l1-artifacts": "5.0.0-nightly.20260709",
79
+ "@aztec/node-keystore": "5.0.0-nightly.20260709",
80
+ "@aztec/node-lib": "5.0.0-nightly.20260709",
81
+ "@aztec/noir-protocol-circuits-types": "5.0.0-nightly.20260709",
82
+ "@aztec/p2p": "5.0.0-nightly.20260709",
83
+ "@aztec/protocol-contracts": "5.0.0-nightly.20260709",
84
+ "@aztec/prover-client": "5.0.0-nightly.20260709",
85
+ "@aztec/prover-node": "5.0.0-nightly.20260709",
86
+ "@aztec/sequencer-client": "5.0.0-nightly.20260709",
87
+ "@aztec/simulator": "5.0.0-nightly.20260709",
88
+ "@aztec/slasher": "5.0.0-nightly.20260709",
89
+ "@aztec/standard-contracts": "5.0.0-nightly.20260709",
90
+ "@aztec/stdlib": "5.0.0-nightly.20260709",
91
+ "@aztec/telemetry-client": "5.0.0-nightly.20260709",
92
+ "@aztec/validator-client": "5.0.0-nightly.20260709",
93
+ "@aztec/validator-ha-signer": "5.0.0-nightly.20260709",
94
+ "@aztec/world-state": "5.0.0-nightly.20260709",
95
95
  "koa": "^2.16.1",
96
96
  "koa-router": "^13.1.1",
97
97
  "tslib": "^2.4.0",
package/src/factory.ts CHANGED
@@ -245,6 +245,23 @@ export async function createAztecNodeService(
245
245
 
246
246
  const collectOffenses = !config.disableValidator || config.enableOffenseCollection;
247
247
 
248
+ // A prover node may still be proving an epoch whose blocks have already finalized on L1. Its proof
249
+ // submission window spans (proofSubmissionEpochs + 1) epochs, so its tx pool must keep finalized txs
250
+ // for at least that long to re-fetch them for proving and failure upload. Operators may configure a
251
+ // larger margin but not a smaller one.
252
+ if (config.enableProverNode) {
253
+ const proofSubmissionEpochs = await rollupContract.getProofSubmissionEpochs();
254
+ const proverRetentionFloorSlots = (proofSubmissionEpochs + 1) * Number(epochDuration);
255
+ const configuredSlots = config.keepFinalizedTxsForSlots ?? 0;
256
+ if (proverRetentionFloorSlots > configuredSlots) {
257
+ log.warn(
258
+ `Increasing keepFinalizedTxsForSlots from ${configuredSlots} to ${proverRetentionFloorSlots} ` +
259
+ `(proof submission window of ${proofSubmissionEpochs + 1} epochs) to retain finalized txs for proving`,
260
+ );
261
+ config.keepFinalizedTxsForSlots = proverRetentionFloorSlots;
262
+ }
263
+ }
264
+
248
265
  // create the tx pool and the p2p client, which will need the l2 block source
249
266
  const p2pClient = await createP2PClient(
250
267
  config,
@@ -3,6 +3,7 @@ import { BlockNumber, type CheckpointNumber, type EpochNumber } from '@aztec/fou
3
3
  import { chunkBy } from '@aztec/foundation/collection';
4
4
  import { Fr } from '@aztec/foundation/curves/bn254';
5
5
  import { type Logger, createLogger } from '@aztec/foundation/log';
6
+ import { sleep } from '@aztec/foundation/sleep';
6
7
  import { MembershipWitness, type SiblingPath } from '@aztec/foundation/trees';
7
8
  import type { AztecAddress } from '@aztec/stdlib/aztec-address';
8
9
  import {
@@ -10,6 +11,7 @@ import {
10
11
  type BlockParameter,
11
12
  type DataInBlock,
12
13
  type L2BlockSource,
14
+ type NormalizedBlockParameter,
13
15
  inspectBlockParameter,
14
16
  } from '@aztec/stdlib/block';
15
17
  import { computePublicDataTreeLeafSlot } from '@aztec/stdlib/hash';
@@ -23,9 +25,16 @@ import {
23
25
  PublicDataWitness,
24
26
  } from '@aztec/stdlib/trees';
25
27
  import type { TxHash } from '@aztec/stdlib/tx';
28
+ import { WorldStateSynchronizerError } from '@aztec/world-state';
26
29
 
27
30
  import { normalizeBlockParameter } from './block_parameter.js';
28
31
 
32
+ /** Attempts at resolving a query and syncing world state to it before giving up (see {@link NodeWorldStateQueries.getWorldState}). */
33
+ const WORLD_STATE_SYNC_ATTEMPTS = 3;
34
+
35
+ /** Delay between world-state sync attempts. */
36
+ const WORLD_STATE_SYNC_RETRY_DELAY_MS = 100;
37
+
29
38
  /** Dependencies required to build a {@link NodeWorldStateQueries}. */
30
39
  export interface NodeWorldStateQueriesDeps {
31
40
  worldStateSynchronizer: WorldStateSynchronizer;
@@ -128,7 +137,7 @@ export class NodeWorldStateQueries {
128
137
  // The Noir circuit checks the archive membership proof against `anchor_block_header.last_archive.root`,
129
138
  // which is the archive tree root BEFORE the anchor block was added (i.e. the state after block N-1).
130
139
  // So we need the world state at block N-1, not block N, to produce a sibling path matching that root.
131
- const referenceBlockNumber = await this.resolveBlockNumber(referenceBlock);
140
+ const referenceBlockNumber = await this.#resolveBlockNumber(referenceBlock);
132
141
  if (referenceBlockNumber === BlockNumber.ZERO) {
133
142
  // Block 0 (the initial block) has an empty archive, so no membership witness can exist.
134
143
  return undefined;
@@ -270,91 +279,96 @@ export class NodeWorldStateQueries {
270
279
  }
271
280
 
272
281
  /**
273
- * Returns an instance of MerkleTreeOperations having first ensured the world state is fully synched
274
- * @param block - The block parameter (block number, block hash, or 'latest') at which to get the data.
282
+ * Returns an instance of MerkleTreeOperations having first ensured the world state is synced to the requested
283
+ * block on the correct fork. Every query variant is resolved to a concrete (block number, block hash), which is
284
+ * threaded through both the sync and the snapshot read so a reorg that replaced the block at that height is
285
+ * detected rather than served silently. Transient failures — a prune landing between resolution and sync, or a
286
+ * fork flip caught at either the sync or the snapshot stage — are retried a few times, re-resolving the query
287
+ * against the updated chain each time; terminal failures — an unknown block hash at resolution, or a block whose
288
+ * history world state has pruned away — are thrown immediately.
289
+ * @param block - The block parameter (block number, block hash, or tag) at which to get the data.
275
290
  * @returns An instance of a committed MerkleTreeOperations
276
291
  */
277
292
  public async getWorldState(block: BlockParameter) {
278
293
  const query = normalizeBlockParameter(block);
279
294
 
280
- // When the request anchors on a specific block hash, resolve it against the archiver up front and
281
- // drive the world-state sync to that exact block number and hash. Resolving against the archiver
282
- // first fails fast with a clear reorg error if the hash is unknown, and passing the hash to the
283
- // synchronizer makes the sync reorg-aware: it barriers until the archive-tree commit for that block
284
- // has landed and verifies it matches the requested fork, instead of syncing to bare latest height
285
- // and then racing the snapshot read below against an in-flight archive-tree write.
286
- const requestedHash = 'hash' in query ? query.hash : undefined;
287
- const anchorBlockNumber = requestedHash !== undefined ? await this.resolveBlockNumber(query) : undefined;
288
-
289
- let blockSyncedTo: BlockNumber = BlockNumber.ZERO;
290
- try {
291
- // Attempt to sync the world state if necessary
292
- blockSyncedTo = await this.#syncWorldState(anchorBlockNumber, requestedHash);
293
- } catch (err) {
294
- this.log.error(`Error getting world state: ${err}`);
295
+ for (let attempt = 1; ; attempt++) {
296
+ try {
297
+ return await this.#resolveWorldState(query);
298
+ } catch (err) {
299
+ if (attempt >= WORLD_STATE_SYNC_ATTEMPTS || !(err instanceof WorldStateSynchronizerError)) {
300
+ throw err;
301
+ }
302
+ this.log.verbose(`Retrying world state query after sync failure: ${err.message}`, {
303
+ attempt,
304
+ block: inspectBlockParameter(block),
305
+ });
306
+ await sleep(WORLD_STATE_SYNC_RETRY_DELAY_MS);
307
+ }
295
308
  }
309
+ }
296
310
 
311
+ /**
312
+ * Resolves `query` to a concrete (block number, block hash), syncs world state to that exact fork, and returns
313
+ * the committed db (for `proposed` queries) or the fork-verified snapshot at the resolved block.
314
+ */
315
+ async #resolveWorldState(query: NormalizedBlockParameter) {
316
+ // User requests 'latest on the current fork', so the committed db is returned unverified
297
317
  if ('tag' in query && query.tag === 'proposed') {
298
- this.log.debug(`Using committed db for latest block, world state synced upto ${blockSyncedTo}`);
318
+ this.log.debug(`Using committed db for latest block`);
319
+ await this.worldStateSynchronizer.syncImmediate();
299
320
  return this.worldStateSynchronizer.getCommitted();
300
321
  }
301
322
 
302
- const blockNumber = anchorBlockNumber ?? (await this.resolveBlockNumber(query));
323
+ // Resolve the query against the block source BEFORE syncing to a concrete (number, hash), and drive the sync to
324
+ // that exact fork. Resolving after the sync races the block source: the resolved tip can advance past what world
325
+ // state synced while the sync is in flight. Passing the hash makes the sync reorg-aware — it barriers until the
326
+ // archive-tree commit for that block has landed and verifies it matches the requested fork, throwing otherwise.
327
+ const { blockNumber, blockHash } = await this.#resolveBlockNumberAndHash(query);
328
+ const blockSyncedTo = await this.worldStateSynchronizer.syncImmediate(blockNumber, blockHash);
329
+
330
+ // The fork could flip between it returning and the snapshot being read, so getVerifiedSnapshot pins the
331
+ // returned view to the resolved fork (re-resolved by the retry loop on mismatch).
332
+ this.log.debug(`Using verified snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
333
+ return await this.worldStateSynchronizer.getVerifiedSnapshot(blockNumber, blockHash);
334
+ }
303
335
 
304
- // Check it's within world state sync range
305
- if (blockNumber > blockSyncedTo) {
306
- throw new Error(
307
- `Queried block ${inspectBlockParameter(block)} not yet synced by the node (node is synced upto ${blockSyncedTo}).`,
308
- );
336
+ /** Resolves any {@link BlockParameter} variant to its concrete `(blockNumber, blockHash)` via the block source. */
337
+ async #resolveBlockNumberAndHash(
338
+ query: NormalizedBlockParameter,
339
+ ): Promise<{ blockNumber: BlockNumber; blockHash: BlockHash }> {
340
+ const blockData = await this.blockSource.getBlockData(query);
341
+ if (blockData === undefined) {
342
+ this.#throwOnUndefinedBlockData(query);
309
343
  }
310
- this.log.debug(`Using snapshot for block ${blockNumber}, world state synced upto ${blockSyncedTo}`);
311
-
312
- const snapshot = this.worldStateSynchronizer.getSnapshot(blockNumber);
313
-
314
- // Double-check world-state synced to the same block hash as was requested.
315
- // Block 0 is skipped: the snapshot returned by `getSnapshot(0)` is the *pre*-genesis archive
316
- // (size 0), so leaf 0 is not yet inserted from that snapshot's view even though block 0's hash
317
- // does live at archive index 0 in the committed tree. The genesis hash is already validated by
318
- // the archiver when it resolves the hash query to block number 0.
319
- if (requestedHash !== undefined && blockNumber !== BlockNumber.ZERO) {
320
- const blockHash = await snapshot.getLeafValue(MerkleTreeId.ARCHIVE, BigInt(blockNumber));
321
- if (!blockHash || !requestedHash.equals(blockHash)) {
322
- throw new Error(
323
- `Block hash ${requestedHash.toString()} not found in world state at block number ${blockNumber} (world state has ${blockHash?.toString() ?? 'no hash'} at that index, genesis header hash is ${this.blockSource.getGenesisBlockHash().toString()}). If the node API has been queried with anchor block hash possibly a reorg has occurred.`,
324
- );
325
- }
326
- }
327
-
328
- return snapshot;
344
+ return { blockNumber: blockData.header.getBlockNumber(), blockHash: blockData.blockHash };
329
345
  }
330
346
 
331
347
  /** Resolves any {@link BlockParameter} variant to a concrete block number. */
332
- public async resolveBlockNumber(block: BlockParameter): Promise<BlockNumber> {
333
- const query = normalizeBlockParameter(block);
334
- const blockNumber = await this.blockSource.getBlockNumber(query);
348
+ async #resolveBlockNumber(block: BlockParameter): Promise<BlockNumber> {
349
+ const blockQuery = normalizeBlockParameter(block);
350
+ const blockNumber = await this.blockSource.getBlockNumber(blockQuery);
335
351
  if (blockNumber === undefined) {
336
- if ('hash' in query) {
337
- throw new Error(
338
- `Block hash ${query.hash.toString()} not found when querying world state. If the node API has been queried with anchor block hash possibly a reorg has occurred.`,
339
- );
340
- }
341
- if ('archive' in query) {
342
- throw new Error(`Block with archive ${query.archive.toString()} not found.`);
343
- }
344
- throw new Error(`Block not found for ${inspectBlockParameter(block)}.`);
352
+ this.#throwOnUndefinedBlockData(blockQuery);
345
353
  }
346
354
  return blockNumber;
347
355
  }
348
356
 
349
357
  /**
350
- * Ensure the world state is synced.
351
- * @param targetBlockNumber - Block to sync up to. Defaults to the latest block known to the archiver.
352
- * @param blockHash - If provided, the synchronizer verifies the block at `targetBlockNumber` matches this
353
- * hash, resyncing (and so detecting reorgs) if it does not yet match or has been reorged away.
354
- * @returns A promise that fulfils once the world state is synced
358
+ * Hash and archive misses are terminal (an unknown block, likely a reorg); tag and number misses are transient —
359
+ * the block may have been pruned between the tag->number resolution and this data read, or may simply not have
360
+ * arrived yet and surface as {@link WorldStateSynchronizerError} so the retry loop re-resolves against the
361
+ * current chain.
355
362
  */
356
- async #syncWorldState(targetBlockNumber?: BlockNumber, blockHash?: BlockHash): Promise<BlockNumber> {
357
- const target = targetBlockNumber ?? (await this.blockSource.getBlockNumber());
358
- return await this.worldStateSynchronizer.syncImmediate(target, blockHash);
363
+ #throwOnUndefinedBlockData(query: NormalizedBlockParameter): never {
364
+ if ('hash' in query) {
365
+ throw new Error(
366
+ `Block hash ${query.hash.toString()} not found when resolving query. If the node API has been queried with anchor block hash possibly a reorg has occurred.`,
367
+ );
368
+ }
369
+ if ('archive' in query) {
370
+ throw new Error(`Block with archive ${query.archive.toString()} not found when resolving query.`);
371
+ }
372
+ throw new WorldStateSynchronizerError(`Block not found for ${inspectBlockParameter(query)} when resolving query.`);
359
373
  }
360
374
  }