@aztec/validator-client 0.0.1-commit.9ee6fcc6 → 0.0.1-commit.9ef841308

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/README.md CHANGED
@@ -158,13 +158,11 @@ Time | Proposer | Validator
158
158
 
159
159
  | Flag | Purpose |
160
160
  | ------------------------------------- | -------------------------------------------------------------------------------------- |
161
- | `validatorReexecute` | Re-execute transactions to verify proposals |
162
161
  | `fishermanMode` | Validate proposals but don't broadcast attestations (monitoring only) |
163
162
  | `alwaysReexecuteBlockProposals` | Force re-execution even when not in committee |
164
163
  | `slashBroadcastedInvalidBlockPenalty` | Penalty amount for invalid proposals (0 = disabled) |
165
164
  | `slashDuplicateProposalPenalty` | Penalty amount for duplicate proposals (0 = disabled) |
166
165
  | `slashDuplicateAttestationPenalty` | Penalty amount for duplicate attestations (0 = disabled) |
167
- | `validatorReexecuteDeadlineMs` | Time reserved at end of slot for propagation/publishing |
168
166
  | `attestationPollingIntervalMs` | How often to poll for attestations when collecting |
169
167
  | `disabledValidators` | Validator addresses to exclude from duties |
170
168
 
package/dest/config.d.ts CHANGED
@@ -8,4 +8,4 @@ export declare const validatorClientConfigMappings: ConfigMappingsType<Validator
8
8
  * @returns The validator configuration.
9
9
  */
10
10
  export declare function getProverEnvVars(): ValidatorClientConfig;
11
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLGtCQUFrQixFQUt4QixNQUFNLDBCQUEwQixDQUFDO0FBR2xDLE9BQU8sS0FBSyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFN0UsWUFBWSxFQUFFLHFCQUFxQixFQUFFLENBQUM7QUFFdEMsZUFBTyxNQUFNLDZCQUE2QixFQUFFLGtCQUFrQixDQUFDLHFCQUFxQixDQXdGbkYsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBZ0IsZ0JBQWdCLElBQUkscUJBQXFCLENBRXhEIn0=
11
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFDTCxLQUFLLGtCQUFrQixFQUt4QixNQUFNLDBCQUEwQixDQUFDO0FBR2xDLE9BQU8sS0FBSyxFQUFFLHFCQUFxQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFFN0UsWUFBWSxFQUFFLHFCQUFxQixFQUFFLENBQUM7QUFFdEMsZUFBTyxNQUFNLDZCQUE2QixFQUFFLGtCQUFrQixDQUFDLHFCQUFxQixDQW1GbkYsQ0FBQztBQUVGOzs7O0dBSUc7QUFDSCx3QkFBZ0IsZ0JBQWdCLElBQUkscUJBQXFCLENBRXhEIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC,eAAO,MAAM,6BAA6B,EAAE,kBAAkB,CAAC,qBAAqB,CAwFnF,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,KAAK,kBAAkB,EAKxB,MAAM,0BAA0B,CAAC;AAGlC,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,iCAAiC,CAAC;AAE7E,YAAY,EAAE,qBAAqB,EAAE,CAAC;AAEtC,eAAO,MAAM,6BAA6B,EAAE,kBAAkB,CAAC,qBAAqB,CAmFnF,CAAC;AAEF;;;;GAIG;AACH,wBAAgB,gBAAgB,IAAI,qBAAqB,CAExD"}
package/dest/config.js CHANGED
@@ -31,11 +31,6 @@ export const validatorClientConfigMappings = {
31
31
  description: 'Interval between polling for new attestations',
32
32
  ...numberConfigHelper(200)
33
33
  },
34
- validatorReexecute: {
35
- env: 'VALIDATOR_REEXECUTE',
36
- description: 'Re-execute transactions before attesting',
37
- ...booleanConfigHelper(true)
38
- },
39
34
  alwaysReexecuteBlockProposals: {
40
35
  description: 'Whether to always reexecute block proposals, even for non-validator nodes (useful for monitoring network status).',
41
36
  defaultValue: true
package/dest/factory.d.ts CHANGED
@@ -8,19 +8,20 @@ import type { ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/s
8
8
  import type { L1ToL2MessageSource } from '@aztec/stdlib/messaging';
9
9
  import type { TelemetryClient } from '@aztec/telemetry-client';
10
10
  import type { SlashingProtectionDatabase } from '@aztec/validator-ha-signer/types';
11
- import { BlockProposalHandler } from './block_proposal_handler.js';
12
11
  import type { FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
12
+ import { ProposalHandler } from './proposal_handler.js';
13
13
  import { ValidatorClient } from './validator.js';
14
- export declare function createBlockProposalHandler(config: ValidatorClientFullConfig, deps: {
14
+ export declare function createProposalHandler(config: ValidatorClientFullConfig, deps: {
15
15
  checkpointsBuilder: FullNodeCheckpointsBuilder;
16
16
  worldState: WorldStateSynchronizer;
17
17
  blockSource: L2BlockSource & L2BlockSink;
18
18
  l1ToL2MessageSource: L1ToL2MessageSource;
19
19
  p2pClient: P2PClient;
20
20
  epochCache: EpochCache;
21
+ blobClient: BlobClientInterface;
21
22
  dateProvider: DateProvider;
22
23
  telemetry: TelemetryClient;
23
- }): BlockProposalHandler;
24
+ }): ProposalHandler;
24
25
  export declare function createValidatorClient(config: ValidatorClientFullConfig, deps: {
25
26
  checkpointsBuilder: FullNodeCheckpointsBuilder;
26
27
  worldState: WorldStateSynchronizer;
@@ -34,4 +35,4 @@ export declare function createValidatorClient(config: ValidatorClientFullConfig,
34
35
  blobClient: BlobClientInterface;
35
36
  slashingProtectionDb?: SlashingProtectionDatabase;
36
37
  }): Promise<ValidatorClient> | undefined;
37
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQTBCLEtBQUssU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3BFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEtBQUssRUFBRSx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pHLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDL0QsT0FBTyxLQUFLLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUVuRixPQUFPLEVBQUUsb0JBQW9CLEVBQUUsTUFBTSw2QkFBNkIsQ0FBQztBQUNuRSxPQUFPLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRTFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVqRCx3QkFBZ0IsMEJBQTBCLENBQ3hDLE1BQU0sRUFBRSx5QkFBeUIsRUFDakMsSUFBSSxFQUFFO0lBQ0osa0JBQWtCLEVBQUUsMEJBQTBCLENBQUM7SUFDL0MsVUFBVSxFQUFFLHNCQUFzQixDQUFDO0lBQ25DLFdBQVcsRUFBRSxhQUFhLEdBQUcsV0FBVyxDQUFDO0lBQ3pDLG1CQUFtQixFQUFFLG1CQUFtQixDQUFDO0lBQ3pDLFNBQVMsRUFBRSxTQUFTLENBQUM7SUFDckIsVUFBVSxFQUFFLFVBQVUsQ0FBQztJQUN2QixZQUFZLEVBQUUsWUFBWSxDQUFDO0lBQzNCLFNBQVMsRUFBRSxlQUFlLENBQUM7Q0FDNUIsd0JBb0JGO0FBRUQsd0JBQWdCLHFCQUFxQixDQUNuQyxNQUFNLEVBQUUseUJBQXlCLEVBQ2pDLElBQUksRUFBRTtJQUNKLGtCQUFrQixFQUFFLDBCQUEwQixDQUFDO0lBQy9DLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztJQUNuQyxTQUFTLEVBQUUsU0FBUyxDQUFDO0lBQ3JCLFdBQVcsRUFBRSxhQUFhLEdBQUcsV0FBVyxDQUFDO0lBQ3pDLG1CQUFtQixFQUFFLG1CQUFtQixDQUFDO0lBQ3pDLFNBQVMsRUFBRSxlQUFlLENBQUM7SUFDM0IsWUFBWSxFQUFFLFlBQVksQ0FBQztJQUMzQixVQUFVLEVBQUUsVUFBVSxDQUFDO0lBQ3ZCLGVBQWUsRUFBRSxlQUFlLEdBQUcsU0FBUyxDQUFDO0lBQzdDLFVBQVUsRUFBRSxtQkFBbUIsQ0FBQztJQUNoQyxvQkFBb0IsQ0FBQyxFQUFFLDBCQUEwQixDQUFDO0NBQ25ELHdDQXNCRiJ9
38
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZmFjdG9yeS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL2ZhY3RvcnkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUNyRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUNyRCxPQUFPLEtBQUssRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUM1RCxPQUFPLEtBQUssRUFBRSxlQUFlLEVBQUUsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RCxPQUFPLEVBQTBCLEtBQUssU0FBUyxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQ3BFLE9BQU8sS0FBSyxFQUFFLFdBQVcsRUFBRSxhQUFhLEVBQUUsTUFBTSxxQkFBcUIsQ0FBQztBQUN0RSxPQUFPLEtBQUssRUFBRSx5QkFBeUIsRUFBRSxzQkFBc0IsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQ3pHLE9BQU8sS0FBSyxFQUFFLG1CQUFtQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsZUFBZSxFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFDL0QsT0FBTyxLQUFLLEVBQUUsMEJBQTBCLEVBQUUsTUFBTSxrQ0FBa0MsQ0FBQztBQUVuRixPQUFPLEtBQUssRUFBRSwwQkFBMEIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBRTFFLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQztBQUN4RCxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFFakQsd0JBQWdCLHFCQUFxQixDQUNuQyxNQUFNLEVBQUUseUJBQXlCLEVBQ2pDLElBQUksRUFBRTtJQUNKLGtCQUFrQixFQUFFLDBCQUEwQixDQUFDO0lBQy9DLFVBQVUsRUFBRSxzQkFBc0IsQ0FBQztJQUNuQyxXQUFXLEVBQUUsYUFBYSxHQUFHLFdBQVcsQ0FBQztJQUN6QyxtQkFBbUIsRUFBRSxtQkFBbUIsQ0FBQztJQUN6QyxTQUFTLEVBQUUsU0FBUyxDQUFDO0lBQ3JCLFVBQVUsRUFBRSxVQUFVLENBQUM7SUFDdkIsVUFBVSxFQUFFLG1CQUFtQixDQUFDO0lBQ2hDLFlBQVksRUFBRSxZQUFZLENBQUM7SUFDM0IsU0FBUyxFQUFFLGVBQWUsQ0FBQztDQUM1QixtQkFxQkY7QUFFRCx3QkFBZ0IscUJBQXFCLENBQ25DLE1BQU0sRUFBRSx5QkFBeUIsRUFDakMsSUFBSSxFQUFFO0lBQ0osa0JBQWtCLEVBQUUsMEJBQTBCLENBQUM7SUFDL0MsVUFBVSxFQUFFLHNCQUFzQixDQUFDO0lBQ25DLFNBQVMsRUFBRSxTQUFTLENBQUM7SUFDckIsV0FBVyxFQUFFLGFBQWEsR0FBRyxXQUFXLENBQUM7SUFDekMsbUJBQW1CLEVBQUUsbUJBQW1CLENBQUM7SUFDekMsU0FBUyxFQUFFLGVBQWUsQ0FBQztJQUMzQixZQUFZLEVBQUUsWUFBWSxDQUFDO0lBQzNCLFVBQVUsRUFBRSxVQUFVLENBQUM7SUFDdkIsZUFBZSxFQUFFLGVBQWUsR0FBRyxTQUFTLENBQUM7SUFDN0MsVUFBVSxFQUFFLG1CQUFtQixDQUFDO0lBQ2hDLG9CQUFvQixDQUFDLEVBQUUsMEJBQTBCLENBQUM7Q0FDbkQsd0NBc0JGIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAEnF,OAAO,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AACnE,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,0BAA0B,CACxC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,eAAe,CAAC;CAC5B,wBAoBF;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,UAAU,EAAE,mBAAmB,CAAC;IAChC,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;CACnD,wCAsBF"}
1
+ {"version":3,"file":"factory.d.ts","sourceRoot":"","sources":["../src/factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,2BAA2B,CAAC;AACrE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AACrD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAA0B,KAAK,SAAS,EAAE,MAAM,YAAY,CAAC;AACpE,OAAO,KAAK,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACtE,OAAO,KAAK,EAAE,yBAAyB,EAAE,sBAAsB,EAAE,MAAM,iCAAiC,CAAC;AACzG,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAC/D,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAEnF,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,yBAAyB,CAAC;AAE1E,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAEjD,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,SAAS,CAAC;IACrB,UAAU,EAAE,UAAU,CAAC;IACvB,UAAU,EAAE,mBAAmB,CAAC;IAChC,YAAY,EAAE,YAAY,CAAC;IAC3B,SAAS,EAAE,eAAe,CAAC;CAC5B,mBAqBF;AAED,wBAAgB,qBAAqB,CACnC,MAAM,EAAE,yBAAyB,EACjC,IAAI,EAAE;IACJ,kBAAkB,EAAE,0BAA0B,CAAC;IAC/C,UAAU,EAAE,sBAAsB,CAAC;IACnC,SAAS,EAAE,SAAS,CAAC;IACrB,WAAW,EAAE,aAAa,GAAG,WAAW,CAAC;IACzC,mBAAmB,EAAE,mBAAmB,CAAC;IACzC,SAAS,EAAE,eAAe,CAAC;IAC3B,YAAY,EAAE,YAAY,CAAC;IAC3B,UAAU,EAAE,UAAU,CAAC;IACvB,eAAe,EAAE,eAAe,GAAG,SAAS,CAAC;IAC7C,UAAU,EAAE,mBAAmB,CAAC;IAChC,oBAAoB,CAAC,EAAE,0BAA0B,CAAC;CACnD,wCAsBF"}
package/dest/factory.js CHANGED
@@ -1,14 +1,14 @@
1
1
  import { BlockProposalValidator } from '@aztec/p2p';
2
- import { BlockProposalHandler } from './block_proposal_handler.js';
3
2
  import { ValidatorMetrics } from './metrics.js';
3
+ import { ProposalHandler } from './proposal_handler.js';
4
4
  import { ValidatorClient } from './validator.js';
5
- export function createBlockProposalHandler(config, deps) {
5
+ export function createProposalHandler(config, deps) {
6
6
  const metrics = new ValidatorMetrics(deps.telemetry);
7
7
  const blockProposalValidator = new BlockProposalValidator(deps.epochCache, {
8
8
  txsPermitted: !config.disableTransactions,
9
9
  maxTxsPerBlock: config.validateMaxTxsPerBlock ?? config.validateMaxTxsPerCheckpoint
10
10
  });
11
- return new BlockProposalHandler(deps.checkpointsBuilder, deps.worldState, deps.blockSource, deps.l1ToL2MessageSource, deps.p2pClient.getTxProvider(), blockProposalValidator, deps.epochCache, config, metrics, deps.dateProvider, deps.telemetry);
11
+ return new ProposalHandler(deps.checkpointsBuilder, deps.worldState, deps.blockSource, deps.l1ToL2MessageSource, deps.p2pClient.getTxProvider(), blockProposalValidator, deps.epochCache, config, deps.blobClient, metrics, deps.dateProvider, deps.telemetry);
12
12
  }
13
13
  export function createValidatorClient(config, deps) {
14
14
  if (config.disableValidator || !deps.keyStoreManager) {
package/dest/index.d.ts CHANGED
@@ -1,7 +1,7 @@
1
- export * from './block_proposal_handler.js';
1
+ export * from './proposal_handler.js';
2
2
  export * from './checkpoint_builder.js';
3
3
  export * from './config.js';
4
4
  export * from './factory.js';
5
5
  export * from './validator.js';
6
6
  export * from './key_store/index.js';
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLDZCQUE2QixDQUFDO0FBQzVDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLHNCQUFzQixDQUFDIn0=
7
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxjQUFjLHVCQUF1QixDQUFDO0FBQ3RDLGNBQWMseUJBQXlCLENBQUM7QUFDeEMsY0FBYyxhQUFhLENBQUM7QUFDNUIsY0FBYyxjQUFjLENBQUM7QUFDN0IsY0FBYyxnQkFBZ0IsQ0FBQztBQUMvQixjQUFjLHNCQUFzQixDQUFDIn0=
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,6BAA6B,CAAC;AAC5C,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,yBAAyB,CAAC;AACxC,cAAc,aAAa,CAAC;AAC5B,cAAc,cAAc,CAAC;AAC7B,cAAc,gBAAgB,CAAC;AAC/B,cAAc,sBAAsB,CAAC"}
package/dest/index.js CHANGED
@@ -1,4 +1,4 @@
1
- export * from './block_proposal_handler.js';
1
+ export * from './proposal_handler.js';
2
2
  export * from './checkpoint_builder.js';
3
3
  export * from './config.js';
4
4
  export * from './factory.js';
package/dest/metrics.d.ts CHANGED
@@ -2,7 +2,7 @@ import type { EpochNumber } from '@aztec/foundation/branded-types';
2
2
  import type { EthAddress } from '@aztec/foundation/eth-address';
3
3
  import type { BlockProposal } from '@aztec/stdlib/p2p';
4
4
  import { type TelemetryClient } from '@aztec/telemetry-client';
5
- import type { BlockProposalValidationFailureReason } from './block_proposal_handler.js';
5
+ import type { BlockProposalValidationFailureReason } from './proposal_handler.js';
6
6
  export declare class ValidatorMetrics {
7
7
  private failedReexecutionCounter;
8
8
  private successfulAttestationsCount;
@@ -24,4 +24,4 @@ export declare class ValidatorMetrics {
24
24
  /** Increment the count of epochs in which the given attester submitted at least one attestation. */
25
25
  incAttestedEpochCount(attester: EthAddress): void;
26
26
  }
27
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUtMLEtBQUssZUFBZSxFQUdyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sS0FBSyxFQUFFLG9DQUFvQyxFQUFFLE1BQU0sNkJBQTZCLENBQUM7QUFFeEYscUJBQWEsZ0JBQWdCO0lBQzNCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBZ0I7SUFDaEQsT0FBTyxDQUFDLDJCQUEyQixDQUFnQjtJQUNuRCxPQUFPLENBQUMsa0NBQWtDLENBQWdCO0lBQzFELE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBZ0I7SUFDeEQsT0FBTyxDQUFDLFlBQVksQ0FBUTtJQUM1QixPQUFPLENBQUMsa0JBQWtCLENBQWdCO0lBRTFDLE9BQU8sQ0FBQyxRQUFRLENBQVk7SUFDNUIsT0FBTyxDQUFDLE1BQU0sQ0FBWTtJQUMxQixPQUFPLENBQUMsWUFBWSxDQUFRO0lBRTVCLFlBQVksZUFBZSxFQUFFLGVBQWUsRUFvRDNDO0lBRU0sVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUk5RDtJQUVNLHVCQUF1QixDQUFDLFFBQVEsRUFBRSxhQUFhLFFBTXJEO0lBRU0seUJBQXlCLENBQUMsR0FBRyxFQUFFLE1BQU0sUUFFM0M7SUFFTSxnQ0FBZ0MsQ0FDckMsR0FBRyxFQUFFLE1BQU0sRUFDWCxNQUFNLEVBQUUsb0NBQW9DLEVBQzVDLFdBQVcsRUFBRSxPQUFPLFFBTXJCO0lBRU0sOEJBQThCLENBQ25DLEdBQUcsRUFBRSxNQUFNLEVBQ1gsTUFBTSxFQUFFLG9DQUFvQyxFQUM1QyxXQUFXLEVBQUUsT0FBTyxRQU1yQjtJQUVELDJGQUEyRjtJQUNwRixlQUFlLENBQUMsS0FBSyxFQUFFLFdBQVcsUUFFeEM7SUFFRCxvR0FBb0c7SUFDN0YscUJBQXFCLENBQUMsUUFBUSxFQUFFLFVBQVUsUUFFaEQ7Q0FDRiJ9
27
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibWV0cmljcy5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL21ldHJpY3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDbkUsT0FBTyxLQUFLLEVBQUUsVUFBVSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFDaEUsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFDdkQsT0FBTyxFQUtMLEtBQUssZUFBZSxFQUdyQixNQUFNLHlCQUF5QixDQUFDO0FBRWpDLE9BQU8sS0FBSyxFQUFFLG9DQUFvQyxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFbEYscUJBQWEsZ0JBQWdCO0lBQzNCLE9BQU8sQ0FBQyx3QkFBd0IsQ0FBZ0I7SUFDaEQsT0FBTyxDQUFDLDJCQUEyQixDQUFnQjtJQUNuRCxPQUFPLENBQUMsa0NBQWtDLENBQWdCO0lBQzFELE9BQU8sQ0FBQyxnQ0FBZ0MsQ0FBZ0I7SUFDeEQsT0FBTyxDQUFDLFlBQVksQ0FBUTtJQUM1QixPQUFPLENBQUMsa0JBQWtCLENBQWdCO0lBRTFDLE9BQU8sQ0FBQyxRQUFRLENBQVk7SUFDNUIsT0FBTyxDQUFDLE1BQU0sQ0FBWTtJQUMxQixPQUFPLENBQUMsWUFBWSxDQUFRO0lBRTVCLFlBQVksZUFBZSxFQUFFLGVBQWUsRUFvRDNDO0lBRU0sVUFBVSxDQUFDLElBQUksRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQUUsTUFBTSxRQUk5RDtJQUVNLHVCQUF1QixDQUFDLFFBQVEsRUFBRSxhQUFhLFFBTXJEO0lBRU0seUJBQXlCLENBQUMsR0FBRyxFQUFFLE1BQU0sUUFFM0M7SUFFTSxnQ0FBZ0MsQ0FDckMsR0FBRyxFQUFFLE1BQU0sRUFDWCxNQUFNLEVBQUUsb0NBQW9DLEVBQzVDLFdBQVcsRUFBRSxPQUFPLFFBTXJCO0lBRU0sOEJBQThCLENBQ25DLEdBQUcsRUFBRSxNQUFNLEVBQ1gsTUFBTSxFQUFFLG9DQUFvQyxFQUM1QyxXQUFXLEVBQUUsT0FBTyxRQU1yQjtJQUVELDJGQUEyRjtJQUNwRixlQUFlLENBQUMsS0FBSyxFQUFFLFdBQVcsUUFFeEM7SUFFRCxvR0FBb0c7SUFDN0YscUJBQXFCLENBQUMsUUFBUSxFQUFFLFVBQVUsUUFFaEQ7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAKL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,6BAA6B,CAAC;AAExF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,kCAAkC,CAAgB;IAC1D,OAAO,CAAC,gCAAgC,CAAgB;IACxD,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,kBAAkB,CAAgB;IAE1C,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAE5B,YAAY,eAAe,EAAE,eAAe,EAoD3C;IAEM,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAI9D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,aAAa,QAMrD;IAEM,yBAAyB,CAAC,GAAG,EAAE,MAAM,QAE3C;IAEM,gCAAgC,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;IAEM,8BAA8B,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;IAED,2FAA2F;IACpF,eAAe,CAAC,KAAK,EAAE,WAAW,QAExC;IAED,oGAAoG;IAC7F,qBAAqB,CAAC,QAAQ,EAAE,UAAU,QAEhD;CACF"}
1
+ {"version":3,"file":"metrics.d.ts","sourceRoot":"","sources":["../src/metrics.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAKL,KAAK,eAAe,EAGrB,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,oCAAoC,EAAE,MAAM,uBAAuB,CAAC;AAElF,qBAAa,gBAAgB;IAC3B,OAAO,CAAC,wBAAwB,CAAgB;IAChD,OAAO,CAAC,2BAA2B,CAAgB;IACnD,OAAO,CAAC,kCAAkC,CAAgB;IAC1D,OAAO,CAAC,gCAAgC,CAAgB;IACxD,OAAO,CAAC,YAAY,CAAQ;IAC5B,OAAO,CAAC,kBAAkB,CAAgB;IAE1C,OAAO,CAAC,QAAQ,CAAY;IAC5B,OAAO,CAAC,MAAM,CAAY;IAC1B,OAAO,CAAC,YAAY,CAAQ;IAE5B,YAAY,eAAe,EAAE,eAAe,EAoD3C;IAEM,UAAU,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,QAI9D;IAEM,uBAAuB,CAAC,QAAQ,EAAE,aAAa,QAMrD;IAEM,yBAAyB,CAAC,GAAG,EAAE,MAAM,QAE3C;IAEM,gCAAgC,CACrC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;IAEM,8BAA8B,CACnC,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,oCAAoC,EAC5C,WAAW,EAAE,OAAO,QAMrB;IAED,2FAA2F;IACpF,eAAe,CAAC,KAAK,EAAE,WAAW,QAExC;IAED,oGAAoG;IAC7F,qBAAqB,CAAC,QAAQ,EAAE,UAAU,QAEhD;CACF"}
@@ -0,0 +1,94 @@
1
+ import type { BlobClientInterface } from '@aztec/blob-client/client';
2
+ import type { EpochCache } from '@aztec/epoch-cache';
3
+ import { BlockNumber, CheckpointNumber } from '@aztec/foundation/branded-types';
4
+ import { Fr } from '@aztec/foundation/curves/bn254';
5
+ import type { LogData } from '@aztec/foundation/log';
6
+ import { DateProvider } from '@aztec/foundation/timer';
7
+ import type { P2P, PeerId } from '@aztec/p2p';
8
+ import { BlockProposalValidator } from '@aztec/p2p/msg_validators';
9
+ import type { L2Block, L2BlockSink, L2BlockSource } from '@aztec/stdlib/block';
10
+ import type { ITxProvider, ValidatorClientFullConfig, WorldStateSynchronizer } from '@aztec/stdlib/interfaces/server';
11
+ import { type L1ToL2MessageSource } from '@aztec/stdlib/messaging';
12
+ import type { BlockProposal, CheckpointProposalCore } from '@aztec/stdlib/p2p';
13
+ import type { FailedTx, Tx } from '@aztec/stdlib/tx';
14
+ import { type TelemetryClient, type Tracer } from '@aztec/telemetry-client';
15
+ import type { FullNodeCheckpointsBuilder } from './checkpoint_builder.js';
16
+ import type { ValidatorMetrics } from './metrics.js';
17
+ export type BlockProposalValidationFailureReason = 'invalid_proposal' | 'parent_block_not_found' | 'block_source_not_synced' | 'parent_block_wrong_slot' | 'in_hash_mismatch' | 'global_variables_mismatch' | 'block_number_already_exists' | 'txs_not_available' | 'state_mismatch' | 'failed_txs' | 'initial_state_mismatch' | 'timeout' | 'unknown_error';
18
+ type ReexecuteTransactionsResult = {
19
+ block: L2Block;
20
+ failedTxs: FailedTx[];
21
+ reexecutionTimeMs: number;
22
+ totalManaUsed: number;
23
+ };
24
+ export type BlockProposalValidationSuccessResult = {
25
+ isValid: true;
26
+ blockNumber: BlockNumber;
27
+ reexecutionResult?: ReexecuteTransactionsResult;
28
+ };
29
+ export type BlockProposalValidationFailureResult = {
30
+ isValid: false;
31
+ reason: BlockProposalValidationFailureReason;
32
+ blockNumber?: BlockNumber;
33
+ reexecutionResult?: ReexecuteTransactionsResult;
34
+ };
35
+ export type BlockProposalValidationResult = BlockProposalValidationSuccessResult | BlockProposalValidationFailureResult;
36
+ export type CheckpointProposalValidationResult = {
37
+ isValid: true;
38
+ } | {
39
+ isValid: false;
40
+ reason: string;
41
+ };
42
+ /** Handles block and checkpoint proposals for both validator and non-validator nodes. */
43
+ export declare class ProposalHandler {
44
+ private checkpointsBuilder;
45
+ private worldState;
46
+ private blockSource;
47
+ private l1ToL2MessageSource;
48
+ private txProvider;
49
+ private blockProposalValidator;
50
+ private epochCache;
51
+ private config;
52
+ private blobClient;
53
+ private metrics?;
54
+ private dateProvider;
55
+ private log;
56
+ readonly tracer: Tracer;
57
+ constructor(checkpointsBuilder: FullNodeCheckpointsBuilder, worldState: WorldStateSynchronizer, blockSource: L2BlockSource & L2BlockSink, l1ToL2MessageSource: L1ToL2MessageSource, txProvider: ITxProvider, blockProposalValidator: BlockProposalValidator, epochCache: EpochCache, config: ValidatorClientFullConfig, blobClient: BlobClientInterface, metrics?: ValidatorMetrics | undefined, dateProvider?: DateProvider, telemetry?: TelemetryClient, log?: import("@aztec/foundation/log").Logger);
58
+ /**
59
+ * Registers non-validator handlers for block and checkpoint proposals on the p2p client.
60
+ * Block proposals are always registered. Checkpoint proposals are registered if the blob client can upload.
61
+ */
62
+ register(p2pClient: P2P, shouldReexecute: boolean): ProposalHandler;
63
+ handleBlockProposal(proposal: BlockProposal, proposalSender: PeerId, shouldReexecute: boolean): Promise<BlockProposalValidationResult>;
64
+ private getParentBlock;
65
+ private computeCheckpointNumber;
66
+ /**
67
+ * Validates that a non-first block in a checkpoint has consistent global variables with its parent.
68
+ * For blocks with indexWithinCheckpoint > 0, all global variables except blockNumber must match the parent.
69
+ * @returns A failure result if validation fails, undefined if validation passes
70
+ */
71
+ private validateNonFirstBlockInCheckpoint;
72
+ private getReexecutionDeadline;
73
+ private waitForBlockSourceSync;
74
+ private getReexecuteFailureReason;
75
+ reexecuteTransactions(proposal: BlockProposal, blockNumber: BlockNumber, checkpointNumber: CheckpointNumber, txs: Tx[], l1ToL2Messages: Fr[], previousCheckpointOutHashes: Fr[]): Promise<ReexecuteTransactionsResult>;
76
+ /**
77
+ * Validates a checkpoint proposal and uploads blobs if configured.
78
+ * Used by both non-validator nodes (via register) and the validator client (via delegation).
79
+ */
80
+ handleCheckpointProposal(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<CheckpointProposalValidationResult>;
81
+ /**
82
+ * Validates a checkpoint proposal by building the full checkpoint and comparing it with the proposal.
83
+ * @returns Validation result with isValid flag and reason if invalid.
84
+ */
85
+ validateCheckpointProposal(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<CheckpointProposalValidationResult>;
86
+ /** Extracts checkpoint global variables from a block. */
87
+ private extractCheckpointConstants;
88
+ /** Triggers blob upload for a checkpoint if the blob client can upload (fire and forget). */
89
+ protected tryUploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): void;
90
+ /** Uploads blobs for a checkpoint to the filestore. */
91
+ protected uploadBlobsForCheckpoint(proposal: CheckpointProposalCore, proposalInfo: LogData): Promise<void>;
92
+ }
93
+ export {};
94
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicHJvcG9zYWxfaGFuZGxlci5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vc3JjL3Byb3Bvc2FsX2hhbmRsZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsTUFBTSwyQkFBMkIsQ0FBQztBQUdyRSxPQUFPLEtBQUssRUFBRSxVQUFVLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVyRCxPQUFPLEVBQUUsV0FBVyxFQUFFLGdCQUFnQixFQUFjLE1BQU0saUNBQWlDLENBQUM7QUFFNUYsT0FBTyxFQUFFLEVBQUUsRUFBRSxNQUFNLGdDQUFnQyxDQUFDO0FBRXBELE9BQU8sS0FBSyxFQUFFLE9BQU8sRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBR3JELE9BQU8sRUFBRSxZQUFZLEVBQVMsTUFBTSx5QkFBeUIsQ0FBQztBQUM5RCxPQUFPLEtBQUssRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sWUFBWSxDQUFDO0FBQzlDLE9BQU8sRUFBRSxzQkFBc0IsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ25FLE9BQU8sS0FBSyxFQUFhLE9BQU8sRUFBRSxXQUFXLEVBQUUsYUFBYSxFQUFFLE1BQU0scUJBQXFCLENBQUM7QUFJMUYsT0FBTyxLQUFLLEVBQUUsV0FBVyxFQUFFLHlCQUF5QixFQUFFLHNCQUFzQixFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDdEgsT0FBTyxFQUNMLEtBQUssbUJBQW1CLEVBR3pCLE1BQU0seUJBQXlCLENBQUM7QUFDakMsT0FBTyxLQUFLLEVBQUUsYUFBYSxFQUFFLHNCQUFzQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7QUFFL0UsT0FBTyxLQUFLLEVBQTZCLFFBQVEsRUFBRSxFQUFFLEVBQUUsTUFBTSxrQkFBa0IsQ0FBQztBQVFoRixPQUFPLEVBQUUsS0FBSyxlQUFlLEVBQUUsS0FBSyxNQUFNLEVBQXNCLE1BQU0seUJBQXlCLENBQUM7QUFFaEcsT0FBTyxLQUFL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
@@ -0,0 +1 @@
1
+ {"version":3,"file":"proposal_handler.d.ts","sourceRoot":"","sources":["../src/proposal_handler.ts"],"names":[],"mappings":"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"}
@@ -63,7 +63,9 @@ function _ts_dispose_resources(env) {
63
63
  return next();
64
64
  })(env);
65
65
  }
66
+ import { encodeCheckpointBlobDataFromBlocks, getBlobsPerL1Block } from '@aztec/blob-lib';
66
67
  import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
68
+ import { validateFeeAssetPriceModifier } from '@aztec/ethereum/contracts';
67
69
  import { BlockNumber, CheckpointNumber, SlotNumber } from '@aztec/foundation/branded-types';
68
70
  import { pick } from '@aztec/foundation/collection';
69
71
  import { Fr } from '@aztec/foundation/curves/bn254';
@@ -71,13 +73,14 @@ import { TimeoutError } from '@aztec/foundation/error';
71
73
  import { createLogger } from '@aztec/foundation/log';
72
74
  import { retryUntil } from '@aztec/foundation/retry';
73
75
  import { DateProvider, Timer } from '@aztec/foundation/timer';
76
+ import { validateCheckpoint } from '@aztec/stdlib/checkpoint';
74
77
  import { getEpochAtSlot, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
75
78
  import { Gas } from '@aztec/stdlib/gas';
76
- import { computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
79
+ import { accumulateCheckpointOutHashes, computeInHashFromL1ToL2Messages } from '@aztec/stdlib/messaging';
77
80
  import { MerkleTreeId } from '@aztec/stdlib/trees';
78
81
  import { ReExFailedTxsError, ReExInitialStateMismatchError, ReExStateMismatchError, ReExTimeoutError, TransactionsNotAvailableError } from '@aztec/stdlib/validators';
79
82
  import { getTelemetryClient } from '@aztec/telemetry-client';
80
- export class BlockProposalHandler {
83
+ /** Handles block and checkpoint proposals for both validator and non-validator nodes. */ export class ProposalHandler {
81
84
  checkpointsBuilder;
82
85
  worldState;
83
86
  blockSource;
@@ -86,11 +89,12 @@ export class BlockProposalHandler {
86
89
  blockProposalValidator;
87
90
  epochCache;
88
91
  config;
92
+ blobClient;
89
93
  metrics;
90
94
  dateProvider;
91
95
  log;
92
96
  tracer;
93
- constructor(checkpointsBuilder, worldState, blockSource, l1ToL2MessageSource, txProvider, blockProposalValidator, epochCache, config, metrics, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator:block-proposal-handler')){
97
+ constructor(checkpointsBuilder, worldState, blockSource, l1ToL2MessageSource, txProvider, blockProposalValidator, epochCache, config, blobClient, metrics, dateProvider = new DateProvider(), telemetry = getTelemetryClient(), log = createLogger('validator:proposal-handler')){
94
98
  this.checkpointsBuilder = checkpointsBuilder;
95
99
  this.worldState = worldState;
96
100
  this.blockSource = blockSource;
@@ -99,18 +103,22 @@ export class BlockProposalHandler {
99
103
  this.blockProposalValidator = blockProposalValidator;
100
104
  this.epochCache = epochCache;
101
105
  this.config = config;
106
+ this.blobClient = blobClient;
102
107
  this.metrics = metrics;
103
108
  this.dateProvider = dateProvider;
104
109
  this.log = log;
105
110
  if (config.fishermanMode) {
106
111
  this.log = this.log.createChild('[FISHERMAN]');
107
112
  }
108
- this.tracer = telemetry.getTracer('BlockProposalHandler');
113
+ this.tracer = telemetry.getTracer('ProposalHandler');
109
114
  }
110
- register(p2pClient, shouldReexecute) {
115
+ /**
116
+ * Registers non-validator handlers for block and checkpoint proposals on the p2p client.
117
+ * Block proposals are always registered. Checkpoint proposals are registered if the blob client can upload.
118
+ */ register(p2pClient, shouldReexecute) {
111
119
  // Non-validator handler that processes or re-executes for monitoring but does not attest.
112
120
  // Returns boolean indicating whether the proposal was valid.
113
- const handler = async (proposal, proposalSender)=>{
121
+ const blockHandler = async (proposal, proposalSender)=>{
114
122
  try {
115
123
  const { slotNumber, blockNumber } = proposal;
116
124
  const result = await this.handleBlockProposal(proposal, proposalSender, shouldReexecute);
@@ -137,7 +145,30 @@ export class BlockProposalHandler {
137
145
  return false;
138
146
  }
139
147
  };
140
- p2pClient.registerBlockProposalHandler(handler);
148
+ p2pClient.registerBlockProposalHandler(blockHandler);
149
+ // Register checkpoint proposal handler if blob uploads are enabled and we are reexecuting
150
+ if (this.blobClient.canUpload() && shouldReexecute) {
151
+ const checkpointHandler = async (checkpoint, _sender)=>{
152
+ try {
153
+ const proposalInfo = {
154
+ proposalSlotNumber: checkpoint.slotNumber,
155
+ archive: checkpoint.archive.toString(),
156
+ proposer: checkpoint.getSender()?.toString()
157
+ };
158
+ const result = await this.handleCheckpointProposal(checkpoint, proposalInfo);
159
+ if (result.isValid) {
160
+ this.log.info(`Non-validator checkpoint proposal at slot ${checkpoint.slotNumber} handled`, proposalInfo);
161
+ } else {
162
+ this.log.warn(`Non-validator checkpoint proposal at slot ${checkpoint.slotNumber} failed: ${result.reason}`, proposalInfo);
163
+ }
164
+ } catch (error) {
165
+ this.log.error('Error processing checkpoint proposal in non-validator handler', error);
166
+ }
167
+ // Non-validators don't attest
168
+ return undefined;
169
+ };
170
+ p2pClient.registerCheckpointProposalHandler(checkpointHandler);
171
+ }
141
172
  return this;
142
173
  }
143
174
  async handleBlockProposal(proposal, proposalSender, shouldReexecute) {
@@ -611,4 +642,215 @@ export class BlockProposalHandler {
611
642
  if (result) await result;
612
643
  }
613
644
  }
645
+ /**
646
+ * Validates a checkpoint proposal and uploads blobs if configured.
647
+ * Used by both non-validator nodes (via register) and the validator client (via delegation).
648
+ */ async handleCheckpointProposal(proposal, proposalInfo) {
649
+ const proposer = proposal.getSender();
650
+ if (!proposer) {
651
+ this.log.warn(`Received checkpoint proposal with invalid signature for slot ${proposal.slotNumber}`);
652
+ return {
653
+ isValid: false,
654
+ reason: 'invalid_signature'
655
+ };
656
+ }
657
+ if (!validateFeeAssetPriceModifier(proposal.feeAssetPriceModifier)) {
658
+ this.log.warn(`Received checkpoint proposal with invalid feeAssetPriceModifier ${proposal.feeAssetPriceModifier} for slot ${proposal.slotNumber}`);
659
+ return {
660
+ isValid: false,
661
+ reason: 'invalid_fee_asset_price_modifier'
662
+ };
663
+ }
664
+ const result = await this.validateCheckpointProposal(proposal, proposalInfo);
665
+ // Upload blobs to filestore if validation passed (fire and forget)
666
+ if (result.isValid) {
667
+ this.tryUploadBlobsForCheckpoint(proposal, proposalInfo);
668
+ }
669
+ return result;
670
+ }
671
+ /**
672
+ * Validates a checkpoint proposal by building the full checkpoint and comparing it with the proposal.
673
+ * @returns Validation result with isValid flag and reason if invalid.
674
+ */ async validateCheckpointProposal(proposal, proposalInfo) {
675
+ const slot = proposal.slotNumber;
676
+ // Timeout block syncing at the start of the next slot
677
+ const config = this.checkpointsBuilder.getConfig();
678
+ const nextSlotTimestampSeconds = Number(getTimestampForSlot(SlotNumber(slot + 1), config));
679
+ const timeoutSeconds = Math.max(1, nextSlotTimestampSeconds - Math.floor(this.dateProvider.now() / 1000));
680
+ // Wait for last block to sync by archive
681
+ let lastBlockHeader;
682
+ try {
683
+ lastBlockHeader = await retryUntil(async ()=>{
684
+ await this.blockSource.syncImmediate();
685
+ return this.blockSource.getBlockHeaderByArchive(proposal.archive);
686
+ }, `waiting for block with archive ${proposal.archive.toString()} for slot ${slot}`, timeoutSeconds, 0.5);
687
+ } catch (err) {
688
+ if (err instanceof TimeoutError) {
689
+ this.log.warn(`Timed out waiting for block with archive matching checkpoint proposal`, proposalInfo);
690
+ return {
691
+ isValid: false,
692
+ reason: 'last_block_not_found'
693
+ };
694
+ }
695
+ this.log.error(`Error fetching last block for checkpoint proposal`, err, proposalInfo);
696
+ return {
697
+ isValid: false,
698
+ reason: 'block_fetch_error'
699
+ };
700
+ }
701
+ if (!lastBlockHeader) {
702
+ this.log.warn(`Last block not found for checkpoint proposal`, proposalInfo);
703
+ return {
704
+ isValid: false,
705
+ reason: 'last_block_not_found'
706
+ };
707
+ }
708
+ // Get all full blocks for the slot and checkpoint
709
+ const blocks = await this.blockSource.getBlocksForSlot(slot);
710
+ if (blocks.length === 0) {
711
+ this.log.warn(`No blocks found for slot ${slot}`, proposalInfo);
712
+ return {
713
+ isValid: false,
714
+ reason: 'no_blocks_for_slot'
715
+ };
716
+ }
717
+ // Ensure the last block for this slot matches the archive in the checkpoint proposal
718
+ if (!blocks.at(-1)?.archive.root.equals(proposal.archive)) {
719
+ this.log.warn(`Last block archive mismatch for checkpoint proposal`, proposalInfo);
720
+ return {
721
+ isValid: false,
722
+ reason: 'last_block_archive_mismatch'
723
+ };
724
+ }
725
+ this.log.debug(`Found ${blocks.length} blocks for slot ${slot}`, {
726
+ ...proposalInfo,
727
+ blockNumbers: blocks.map((b)=>b.number)
728
+ });
729
+ // Get checkpoint constants from first block
730
+ const firstBlock = blocks[0];
731
+ const constants = this.extractCheckpointConstants(firstBlock);
732
+ const checkpointNumber = firstBlock.checkpointNumber;
733
+ // Get L1-to-L2 messages for this checkpoint
734
+ const l1ToL2Messages = await this.l1ToL2MessageSource.getL1ToL2Messages(checkpointNumber);
735
+ // Collect the out hashes of all the checkpoints before this one in the same epoch
736
+ const epoch = getEpochAtSlot(slot, this.epochCache.getL1Constants());
737
+ const previousCheckpointOutHashes = (await this.blockSource.getCheckpointsDataForEpoch(epoch)).filter((c)=>c.checkpointNumber < checkpointNumber).map((c)=>c.checkpointOutHash);
738
+ // Fork world state at the block before the first block
739
+ const parentBlockNumber = BlockNumber(firstBlock.number - 1);
740
+ const fork = await this.worldState.fork(parentBlockNumber);
741
+ try {
742
+ // Create checkpoint builder with all existing blocks
743
+ const checkpointBuilder = await this.checkpointsBuilder.openCheckpoint(checkpointNumber, constants, proposal.feeAssetPriceModifier, l1ToL2Messages, previousCheckpointOutHashes, fork, blocks, this.log.getBindings());
744
+ // Complete the checkpoint to get computed values
745
+ const computedCheckpoint = await checkpointBuilder.completeCheckpoint();
746
+ // Compare checkpoint header with proposal
747
+ if (!computedCheckpoint.header.equals(proposal.checkpointHeader)) {
748
+ this.log.warn(`Checkpoint header mismatch`, {
749
+ ...proposalInfo,
750
+ computed: computedCheckpoint.header.toInspect(),
751
+ proposal: proposal.checkpointHeader.toInspect()
752
+ });
753
+ return {
754
+ isValid: false,
755
+ reason: 'checkpoint_header_mismatch'
756
+ };
757
+ }
758
+ // Compare archive root with proposal
759
+ if (!computedCheckpoint.archive.root.equals(proposal.archive)) {
760
+ this.log.warn(`Archive root mismatch`, {
761
+ ...proposalInfo,
762
+ computed: computedCheckpoint.archive.root.toString(),
763
+ proposal: proposal.archive.toString()
764
+ });
765
+ return {
766
+ isValid: false,
767
+ reason: 'archive_mismatch'
768
+ };
769
+ }
770
+ // Check that the accumulated epoch out hash matches the value in the proposal.
771
+ // The epoch out hash is the accumulated hash of all checkpoint out hashes in the epoch.
772
+ const checkpointOutHash = computedCheckpoint.getCheckpointOutHash();
773
+ const computedEpochOutHash = accumulateCheckpointOutHashes([
774
+ ...previousCheckpointOutHashes,
775
+ checkpointOutHash
776
+ ]);
777
+ const proposalEpochOutHash = proposal.checkpointHeader.epochOutHash;
778
+ if (!computedEpochOutHash.equals(proposalEpochOutHash)) {
779
+ this.log.warn(`Epoch out hash mismatch`, {
780
+ proposalEpochOutHash: proposalEpochOutHash.toString(),
781
+ computedEpochOutHash: computedEpochOutHash.toString(),
782
+ checkpointOutHash: checkpointOutHash.toString(),
783
+ previousCheckpointOutHashes: previousCheckpointOutHashes.map((h)=>h.toString()),
784
+ ...proposalInfo
785
+ });
786
+ return {
787
+ isValid: false,
788
+ reason: 'out_hash_mismatch'
789
+ };
790
+ }
791
+ // Final round of validations on the checkpoint, just in case.
792
+ try {
793
+ validateCheckpoint(computedCheckpoint, {
794
+ rollupManaLimit: this.checkpointsBuilder.getConfig().rollupManaLimit,
795
+ maxDABlockGas: this.config.validateMaxDABlockGas,
796
+ maxL2BlockGas: this.config.validateMaxL2BlockGas,
797
+ maxTxsPerBlock: this.config.validateMaxTxsPerBlock,
798
+ maxTxsPerCheckpoint: this.config.validateMaxTxsPerCheckpoint
799
+ });
800
+ } catch (err) {
801
+ this.log.warn(`Checkpoint validation failed: ${err}`, proposalInfo);
802
+ return {
803
+ isValid: false,
804
+ reason: 'checkpoint_validation_failed'
805
+ };
806
+ }
807
+ this.log.verbose(`Checkpoint proposal validation successful for slot ${slot}`, proposalInfo);
808
+ return {
809
+ isValid: true
810
+ };
811
+ } finally{
812
+ await fork.close();
813
+ }
814
+ }
815
+ /** Extracts checkpoint global variables from a block. */ extractCheckpointConstants(block) {
816
+ const gv = block.header.globalVariables;
817
+ return {
818
+ chainId: gv.chainId,
819
+ version: gv.version,
820
+ slotNumber: gv.slotNumber,
821
+ timestamp: gv.timestamp,
822
+ coinbase: gv.coinbase,
823
+ feeRecipient: gv.feeRecipient,
824
+ gasFees: gv.gasFees
825
+ };
826
+ }
827
+ /** Triggers blob upload for a checkpoint if the blob client can upload (fire and forget). */ tryUploadBlobsForCheckpoint(proposal, proposalInfo) {
828
+ if (this.blobClient.canUpload()) {
829
+ void this.uploadBlobsForCheckpoint(proposal, proposalInfo);
830
+ }
831
+ }
832
+ /** Uploads blobs for a checkpoint to the filestore. */ async uploadBlobsForCheckpoint(proposal, proposalInfo) {
833
+ try {
834
+ const lastBlockHeader = await this.blockSource.getBlockHeaderByArchive(proposal.archive);
835
+ if (!lastBlockHeader) {
836
+ this.log.warn(`Failed to get last block header for blob upload`, proposalInfo);
837
+ return;
838
+ }
839
+ const blocks = await this.blockSource.getBlocksForSlot(proposal.slotNumber);
840
+ if (blocks.length === 0) {
841
+ this.log.warn(`No blocks found for blob upload`, proposalInfo);
842
+ return;
843
+ }
844
+ const blockBlobData = blocks.map((b)=>b.toBlockBlobData());
845
+ const blobFields = encodeCheckpointBlobDataFromBlocks(blockBlobData);
846
+ const blobs = await getBlobsPerL1Block(blobFields);
847
+ await this.blobClient.sendBlobsToFilestore(blobs);
848
+ this.log.debug(`Uploaded ${blobs.length} blobs to filestore for checkpoint at slot ${proposal.slotNumber}`, {
849
+ ...proposalInfo,
850
+ numBlobs: blobs.length
851
+ });
852
+ } catch (err) {
853
+ this.log.warn(`Failed to upload blobs for checkpoint: ${err}`, proposalInfo);
854
+ }
855
+ }
614
856
  }