@aztec/epoch-cache 0.0.1-commit.ef17749e1 → 0.0.1-commit.f1b29a41e

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/config.d.ts CHANGED
@@ -1,5 +1,6 @@
1
1
  import { type L1ContractsConfig } from '@aztec/ethereum/config';
2
2
  import { type L1ReaderConfig } from '@aztec/ethereum/l1-reader';
3
- export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'>;
3
+ import { type PipelineConfig } from '@aztec/stdlib/config';
4
+ export type EpochCacheConfig = Pick<L1ReaderConfig & L1ContractsConfig & PipelineConfig, 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration' | 'l1HttpTimeoutMS' | 'enableProposerPipelining'>;
4
5
  export declare function getEpochCacheConfigEnvVars(): EpochCacheConfig;
5
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUUxRixNQUFNLE1BQU0sZ0JBQWdCLEdBQUcsSUFBSSxDQUNqQyxjQUFjLEdBQUcsaUJBQWlCLEVBQ2xDLFdBQVcsR0FBRyxXQUFXLEdBQUcsdUJBQXVCLEdBQUcsc0JBQXNCLENBQzdFLENBQUM7QUFFRix3QkFBZ0IsMEJBQTBCLElBQUksZ0JBQWdCLENBRTdEIn0=
6
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29uZmlnLmQudHMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi9zcmMvY29uZmlnLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxLQUFLLGlCQUFpQixFQUErQixNQUFNLHdCQUF3QixDQUFDO0FBQzdGLE9BQU8sRUFBRSxLQUFLLGNBQWMsRUFBNEIsTUFBTSwyQkFBMkIsQ0FBQztBQUMxRixPQUFPLEVBQUUsS0FBSyxjQUFjLEVBQTRCLE1BQU0sc0JBQXNCLENBQUM7QUFFckYsTUFBTSxNQUFNLGdCQUFnQixHQUFHLElBQUksQ0FDakMsY0FBYyxHQUFHLGlCQUFpQixHQUFHLGNBQWMsRUFDakQsV0FBVyxHQUNYLFdBQVcsR0FDWCx1QkFBdUIsR0FDdkIsc0JBQXNCLEdBQ3RCLGlCQUFpQixHQUNqQiwwQkFBMEIsQ0FDN0IsQ0FBQztBQUVGLHdCQUFnQiwwQkFBMEIsSUFBSSxnQkFBZ0IsQ0FFN0QifQ==
@@ -1 +1 @@
1
- {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA+B,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,2BAA2B,CAAC;AAE1F,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,GAAG,iBAAiB,EAClC,WAAW,GAAG,WAAW,GAAG,uBAAuB,GAAG,sBAAsB,CAC7E,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,iBAAiB,EAA+B,MAAM,wBAAwB,CAAC;AAC7F,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,2BAA2B,CAAC;AAC1F,OAAO,EAAE,KAAK,cAAc,EAA4B,MAAM,sBAAsB,CAAC;AAErF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CACjC,cAAc,GAAG,iBAAiB,GAAG,cAAc,EACjD,WAAW,GACX,WAAW,GACX,uBAAuB,GACvB,sBAAsB,GACtB,iBAAiB,GACjB,0BAA0B,CAC7B,CAAC;AAEF,wBAAgB,0BAA0B,IAAI,gBAAgB,CAE7D"}
package/dest/config.js CHANGED
@@ -1,8 +1,10 @@
1
1
  import { getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
2
2
  import { getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
3
+ import { getPipelineConfigEnvVars } from '@aztec/stdlib/config';
3
4
  export function getEpochCacheConfigEnvVars() {
4
5
  return {
5
6
  ...getL1ReaderConfigFromEnv(),
6
- ...getL1ContractsConfigEnvVars()
7
+ ...getL1ContractsConfigEnvVars(),
8
+ ...getPipelineConfigEnvVars()
7
9
  };
8
10
  }
@@ -4,9 +4,12 @@ import { EthAddress } from '@aztec/foundation/eth-address';
4
4
  import { DateProvider } from '@aztec/foundation/timer';
5
5
  import { type L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
6
6
  import { type EpochCacheConfig } from './config.js';
7
+ /** When proposer pipelining is enabled, the proposer builds one slot ahead. */
8
+ export declare const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
9
+ /** Flat return type for compound epoch/slot getters. */
7
10
  export type EpochAndSlot = {
8
- epoch: EpochNumber;
9
11
  slot: SlotNumber;
12
+ epoch: EpochNumber;
10
13
  ts: bigint;
11
14
  };
12
15
  export type EpochCommitteeInfo = {
@@ -19,18 +22,33 @@ export type EpochCommitteeInfo = {
19
22
  export type SlotTag = 'now' | 'next' | SlotNumber;
20
23
  export interface EpochCacheInterface {
21
24
  getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
25
+ getSlotNow(): SlotNumber;
26
+ getTargetSlot(): SlotNumber;
27
+ getEpochNow(): EpochNumber;
28
+ getTargetEpoch(): EpochNumber;
22
29
  getEpochAndSlotNow(): EpochAndSlot & {
23
30
  nowMs: bigint;
24
31
  };
25
32
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
26
- now: bigint;
33
+ nowSeconds: bigint;
34
+ };
35
+ /** Returns epoch/slot info for the next L1 slot with pipeline offset applied. */
36
+ getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
37
+ nowSeconds: bigint;
27
38
  };
39
+ isProposerPipeliningEnabled(): boolean;
40
+ isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
41
+ isEscapeHatchOpenAtSlot(slot: SlotTag): Promise<boolean>;
28
42
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
29
43
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
30
44
  getCurrentAndNextSlot(): {
31
45
  currentSlot: SlotNumber;
32
46
  nextSlot: SlotNumber;
33
47
  };
48
+ getTargetAndNextSlot(): {
49
+ targetSlot: SlotNumber;
50
+ nextSlot: SlotNumber;
51
+ };
34
52
  getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
35
53
  getRegisteredValidators(): Promise<EthAddress[]>;
36
54
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
@@ -53,29 +71,39 @@ export declare class EpochCache implements EpochCacheInterface {
53
71
  protected readonly config: {
54
72
  cacheSize: number;
55
73
  validatorRefreshIntervalSeconds: number;
74
+ enableProposerPipelining: boolean;
56
75
  };
57
76
  protected cache: Map<EpochNumber, EpochCommitteeInfo>;
58
77
  private allValidators;
59
78
  private lastValidatorRefresh;
60
79
  private readonly log;
80
+ protected enableProposerPipelining: boolean;
61
81
  constructor(rollup: RollupContract, l1constants: L1RollupConstants & {
62
82
  lagInEpochsForValidatorSet: number;
63
83
  lagInEpochsForRandao: number;
64
84
  }, dateProvider?: DateProvider, config?: {
65
85
  cacheSize: number;
66
86
  validatorRefreshIntervalSeconds: number;
87
+ enableProposerPipelining: boolean;
67
88
  });
68
89
  static create(rollupOrAddress: EthAddress | RollupContract, config?: EpochCacheConfig, deps?: {
69
90
  dateProvider?: DateProvider;
70
91
  }): Promise<EpochCache>;
71
92
  getL1Constants(): L1RollupConstants;
93
+ isProposerPipeliningEnabled(): boolean;
94
+ getSlotNow(): SlotNumber;
95
+ getTargetSlot(): SlotNumber;
96
+ getEpochNow(): EpochNumber;
97
+ getTargetEpoch(): EpochNumber;
72
98
  getEpochAndSlotNow(): EpochAndSlot & {
73
99
  nowMs: bigint;
74
100
  };
75
- nowInSeconds(): bigint;
76
101
  private getEpochAndSlotAtSlot;
77
102
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
78
- now: bigint;
103
+ nowSeconds: bigint;
104
+ };
105
+ getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
106
+ nowSeconds: bigint;
79
107
  };
80
108
  private getEpochAndSlotAtTimestamp;
81
109
  getCommitteeForEpoch(epoch: EpochNumber): Promise<EpochCommitteeInfo>;
@@ -106,11 +134,16 @@ export declare class EpochCache implements EpochCacheInterface {
106
134
  */
107
135
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
108
136
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
109
- /** Returns the current and next L2 slot numbers. */
137
+ /** Returns the current and next L2 slot in next eth L1 Slot. */
110
138
  getCurrentAndNextSlot(): {
111
139
  currentSlot: SlotNumber;
112
140
  nextSlot: SlotNumber;
113
141
  };
142
+ /** Returns the target and next L2 slot in the next L1 slot. */
143
+ getTargetAndNextSlot(): {
144
+ targetSlot: SlotNumber;
145
+ nextSlot: SlotNumber;
146
+ };
114
147
  /**
115
148
  * Get the proposer attester address in the given L2 slot
116
149
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
@@ -131,4 +164,4 @@ export declare class EpochCache implements EpochCacheInterface {
131
164
  filterInCommittee(slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
132
165
  getRegisteredValidators(): Promise<EthAddress[]>;
133
166
  }
134
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFDQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFPdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsTUFBTSxNQUFNLFlBQVksR0FBRztJQUN6QixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsRUFBRSxFQUFFLE1BQU0sQ0FBQztDQUNaLENBQUM7QUFFRixNQUFNLE1BQU0sa0JBQWtCLEdBQUc7SUFDL0IsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLFNBQVMsQ0FBQztJQUNwQyxJQUFJLEVBQUUsTUFBTSxDQUFDO0lBQ2IsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQiwrREFBK0Q7SUFDL0QsaUJBQWlCLEVBQUUsT0FBTyxDQUFDO0NBQzVCLENBQUM7QUFFRixNQUFNLE1BQU0sT0FBTyxHQUFHLEtBQUssR0FBRyxNQUFNLEdBQUcsVUFBVSxDQUFDO0FBRWxELE1BQU0sV0FBVyxtQkFBbUI7SUFDbEMsWUFBWSxDQUFDLElBQUksRUFBRSxPQUFPLEdBQUcsU0FBUyxHQUFHLE9BQU8sQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ3JFLGtCQUFrQixJQUFJLFlBQVksR0FBRztRQUFFLEtBQUssRUFBRSxNQUFNLENBQUE7S0FBRSxDQUFDO0lBQ3ZE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
167
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZXBvY2hfY2FjaGUuZC50cyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uL3NyYy9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQW9CLGNBQWMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQzdFLE9BQU8sRUFBRSxXQUFXLEVBQUUsVUFBVSxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxNQUFNLCtCQUErQixDQUFDO0FBRTNELE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSx5QkFBeUIsQ0FBQztBQUN2RCxPQUFPLEVBQ0wsS0FBSyxpQkFBaUIsRUFRdkIsTUFBTSw2QkFBNkIsQ0FBQztBQUlyQyxPQUFPLEVBQUUsS0FBSyxnQkFBZ0IsRUFBOEIsTUFBTSxhQUFhLENBQUM7QUFFaEYsK0VBQStFO0FBQy9FLGVBQU8sTUFBTSwrQkFBK0IsSUFBSSxDQUFDO0FBRWpELHdEQUF3RDtBQUN4RCxNQUFNLE1BQU0sWUFBWSxHQUFHO0lBQ3pCLElBQUksRUFBRSxVQUFVLENBQUM7SUFDakIsS0FBSyxFQUFFLFdBQVcsQ0FBQztJQUNuQixFQUFFLEVBQUUsTUFBTSxDQUFDO0NBQ1osQ0FBQztBQUVGLE1BQU0sTUFBTSxrQkFBa0IsR0FBRztJQUMvQixTQUFTLEVBQUUsVUFBVSxFQUFFLEdBQUcsU0FBUyxDQUFDO0lBQ3BDLElBQUksRUFBRSxNQUFNLENBQUM7SUFDYixLQUFLLEVBQUUsV0FBVyxDQUFDO0lBQ25CLCtEQUErRDtJQUMvRCxpQkFBaUIsRUFBRSxPQUFPLENBQUM7Q0FDNUIsQ0FBQztBQUVGLE1BQU0sTUFBTSxPQUFPLEdBQUcsS0FBSyxHQUFHLE1BQU0sR0FBRyxVQUFVLENBQUM7QUFFbEQsTUFBTSxXQUFXLG1CQUFtQjtJQUNsQyxZQUFZLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxTQUFTLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDckUsVUFB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
@@ -1 +1 @@
1
- {"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"epoch_cache.d.ts","sourceRoot":"","sources":["../src/epoch_cache.ts"],"names":[],"mappings":"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"}
@@ -1,11 +1,14 @@
1
1
  import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { makeL1HttpTransport } from '@aztec/ethereum/client';
2
3
  import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
4
+ import { SlotNumber } from '@aztec/foundation/branded-types';
3
5
  import { EthAddress } from '@aztec/foundation/eth-address';
4
6
  import { createLogger } from '@aztec/foundation/log';
5
7
  import { DateProvider } from '@aztec/foundation/timer';
6
- import { getEpochAtSlot, getEpochNumberAtTimestamp, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
7
- import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
8
+ import { getEpochAtSlot, getEpochNumberAtTimestamp, getNextL1SlotTimestamp, getSlotAtNextL1Block, getSlotAtTimestamp, getSlotRangeForEpoch, getTimestampForSlot } from '@aztec/stdlib/epoch-helpers';
9
+ import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
8
10
  import { getEpochCacheConfigEnvVars } from './config.js';
11
+ /** When proposer pipelining is enabled, the proposer builds one slot ahead. */ export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
9
12
  /**
10
13
  * Epoch cache
11
14
  *
@@ -24,9 +27,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
24
27
  allValidators;
25
28
  lastValidatorRefresh;
26
29
  log;
30
+ enableProposerPipelining;
27
31
  constructor(rollup, l1constants, dateProvider = new DateProvider(), config = {
28
32
  cacheSize: 12,
29
- validatorRefreshIntervalSeconds: 60
33
+ validatorRefreshIntervalSeconds: 60,
34
+ enableProposerPipelining: false
30
35
  }){
31
36
  this.rollup = rollup;
32
37
  this.l1constants = l1constants;
@@ -36,8 +41,10 @@ import { getEpochCacheConfigEnvVars } from './config.js';
36
41
  this.allValidators = new Set();
37
42
  this.lastValidatorRefresh = 0;
38
43
  this.log = createLogger('epoch-cache');
44
+ this.enableProposerPipelining = this.config.enableProposerPipelining;
39
45
  this.log.debug(`Initialized EpochCache`, {
40
- l1constants
46
+ l1constants,
47
+ enableProposerPipelining: this.enableProposerPipelining
41
48
  });
42
49
  }
43
50
  static async create(rollupOrAddress, config, deps = {}) {
@@ -50,14 +57,14 @@ import { getEpochCacheConfigEnvVars } from './config.js';
50
57
  const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
51
58
  const publicClient = createPublicClient({
52
59
  chain: chain.chainInfo,
53
- transport: fallback(config.l1RpcUrls.map((url)=>http(url, {
54
- batch: false
55
- }))),
60
+ transport: makeL1HttpTransport(config.l1RpcUrls, {
61
+ timeout: config.l1HttpTimeoutMS
62
+ }),
56
63
  pollingInterval: config.viemPollingIntervalMS
57
64
  });
58
65
  rollup = new RollupContract(publicClient, rollupOrAddress.toString());
59
66
  }
60
- const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao, targetCommitteeSize] = await Promise.all([
67
+ const [l1StartBlock, l1GenesisTime, proofSubmissionEpochs, slotDuration, epochDuration, lagInEpochsForValidatorSet, lagInEpochsForRandao, targetCommitteeSize, rollupManaLimit] = await Promise.all([
61
68
  rollup.getL1StartBlock(),
62
69
  rollup.getL1GenesisTime(),
63
70
  rollup.getProofSubmissionEpochs(),
@@ -65,7 +72,8 @@ import { getEpochCacheConfigEnvVars } from './config.js';
65
72
  rollup.getEpochDuration(),
66
73
  rollup.getLagInEpochsForValidatorSet(),
67
74
  rollup.getLagInEpochsForRandao(),
68
- rollup.getTargetCommitteeSize()
75
+ rollup.getTargetCommitteeSize(),
76
+ rollup.getManaLimit()
69
77
  ]);
70
78
  const l1RollupConstants = {
71
79
  l1StartBlock,
@@ -76,13 +84,35 @@ import { getEpochCacheConfigEnvVars } from './config.js';
76
84
  ethereumSlotDuration: config.ethereumSlotDuration,
77
85
  lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
78
86
  lagInEpochsForRandao: Number(lagInEpochsForRandao),
79
- targetCommitteeSize: Number(targetCommitteeSize)
87
+ targetCommitteeSize: Number(targetCommitteeSize),
88
+ rollupManaLimit: Number(rollupManaLimit)
80
89
  };
81
- return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
90
+ return new EpochCache(rollup, l1RollupConstants, deps.dateProvider, {
91
+ cacheSize: 12,
92
+ validatorRefreshIntervalSeconds: 60,
93
+ enableProposerPipelining: config.enableProposerPipelining
94
+ });
82
95
  }
83
96
  getL1Constants() {
84
97
  return this.l1constants;
85
98
  }
99
+ isProposerPipeliningEnabled() {
100
+ return this.enableProposerPipelining;
101
+ }
102
+ getSlotNow() {
103
+ return this.getEpochAndSlotNow().slot;
104
+ }
105
+ getTargetSlot() {
106
+ const slotNow = this.getSlotNow();
107
+ const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
108
+ return SlotNumber(slotNow + offset);
109
+ }
110
+ getEpochNow() {
111
+ return this.getEpochAndSlotNow().epoch;
112
+ }
113
+ getTargetEpoch() {
114
+ return getEpochAtSlot(this.getTargetSlot(), this.l1constants);
115
+ }
86
116
  getEpochAndSlotNow() {
87
117
  const nowMs = BigInt(this.dateProvider.now());
88
118
  const nowSeconds = nowMs / 1000n;
@@ -91,32 +121,37 @@ import { getEpochCacheConfigEnvVars } from './config.js';
91
121
  nowMs
92
122
  };
93
123
  }
94
- nowInSeconds() {
95
- return BigInt(Math.floor(this.dateProvider.now() / 1000));
96
- }
97
124
  getEpochAndSlotAtSlot(slot) {
98
- const epoch = getEpochAtSlot(slot, this.l1constants);
99
- const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
100
- return {
101
- epoch,
102
- ts,
103
- slot
104
- };
125
+ return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
105
126
  }
106
127
  getEpochAndSlotInNextL1Slot() {
107
- const now = this.nowInSeconds();
108
- const nextSlotTs = now + BigInt(this.l1constants.ethereumSlotDuration);
128
+ const nowSeconds = this.dateProvider.nowInSeconds();
129
+ const nextSlotTs = getNextL1SlotTimestamp(nowSeconds, this.l1constants);
109
130
  return {
110
131
  ...this.getEpochAndSlotAtTimestamp(nextSlotTs),
111
- now
132
+ nowSeconds: BigInt(nowSeconds)
133
+ };
134
+ }
135
+ getTargetEpochAndSlotInNextL1Slot() {
136
+ if (!this.isProposerPipeliningEnabled()) {
137
+ return this.getEpochAndSlotInNextL1Slot();
138
+ }
139
+ const result = this.getEpochAndSlotInNextL1Slot();
140
+ const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
141
+ const targetSlot = SlotNumber(result.slot + offset);
142
+ return {
143
+ ...result,
144
+ slot: targetSlot,
145
+ epoch: getEpochAtSlot(targetSlot, this.l1constants)
112
146
  };
113
147
  }
114
148
  getEpochAndSlotAtTimestamp(ts) {
115
149
  const slot = getSlotAtTimestamp(ts, this.l1constants);
150
+ const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
116
151
  return {
117
- epoch: getEpochNumberAtTimestamp(ts, this.l1constants),
118
- ts: getTimestampForSlot(slot, this.l1constants),
119
- slot
152
+ slot,
153
+ epoch,
154
+ ts: getTimestampForSlot(slot, this.l1constants)
120
155
  };
121
156
  }
122
157
  getCommitteeForEpoch(epoch) {
@@ -142,7 +177,7 @@ import { getEpochCacheConfigEnvVars } from './config.js';
142
177
  * This is a lightweight helper intended for callers that already have a slot number and only
143
178
  * need the escape hatch flag (without pulling full committee info).
144
179
  */ async isEscapeHatchOpenAtSlot(slot = 'now') {
145
- const epoch = slot === 'now' ? this.getEpochAndSlotNow().epoch : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
180
+ const epoch = slot === 'now' ? this.getEpochNow() : slot === 'next' ? this.getEpochAndSlotInNextL1Slot().epoch : getEpochAtSlot(slot, this.l1constants);
146
181
  return await this.isEscapeHatchOpen(epoch);
147
182
  }
148
183
  /**
@@ -227,14 +262,26 @@ import { getEpochCacheConfigEnvVars } from './config.js';
227
262
  }
228
263
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
229
264
  }
230
- /** Returns the current and next L2 slot numbers. */ getCurrentAndNextSlot() {
231
- const current = this.getEpochAndSlotNow();
265
+ /** Returns the current and next L2 slot in next eth L1 Slot. */ getCurrentAndNextSlot() {
266
+ const currentSlot = this.getSlotNow();
232
267
  const next = this.getEpochAndSlotInNextL1Slot();
233
268
  return {
234
- currentSlot: current.slot,
269
+ currentSlot,
235
270
  nextSlot: next.slot
236
271
  };
237
272
  }
273
+ /** Returns the target and next L2 slot in the next L1 slot. */ getTargetAndNextSlot() {
274
+ const nowSeconds = BigInt(this.dateProvider.nowInSeconds());
275
+ const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
276
+ const currentSlot = getSlotAtTimestamp(nowSeconds, this.l1constants);
277
+ const targetSlot = SlotNumber(currentSlot + offset);
278
+ const nextL2SlotOnL1 = getSlotAtNextL1Block(nowSeconds, this.l1constants);
279
+ const nextSlot = SlotNumber(nextL2SlotOnL1 + offset);
280
+ return {
281
+ targetSlot,
282
+ nextSlot
283
+ };
284
+ }
238
285
  /**
239
286
  * Get the proposer attester address in the given L2 slot
240
287
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
@@ -292,10 +339,11 @@ import { getEpochCacheConfigEnvVars } from './config.js';
292
339
  async getRegisteredValidators() {
293
340
  const validatorRefreshIntervalMs = this.config.validatorRefreshIntervalSeconds * 1000;
294
341
  const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
295
- if (validatorRefreshTime < this.dateProvider.now()) {
296
- const currentSet = await this.rollup.getAttesters();
342
+ const now = this.dateProvider.now();
343
+ if (validatorRefreshTime < now) {
344
+ const currentSet = await this.rollup.getAttesters(BigInt(Math.floor(now / 1000)));
297
345
  this.allValidators = new Set(currentSet.map((v)=>v.toString()));
298
- this.lastValidatorRefresh = this.dateProvider.now();
346
+ this.lastValidatorRefresh = now;
299
347
  }
300
348
  return Array.from(this.allValidators.keys()).map((v)=>EthAddress.fromString(v));
301
349
  }
@@ -1,7 +1,7 @@
1
1
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
2
2
  import { EthAddress } from '@aztec/foundation/eth-address';
3
3
  import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
4
- import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '../epoch_cache.js';
4
+ import { type EpochAndSlot, type EpochCacheInterface, type EpochCommitteeInfo, type SlotTag } from '../epoch_cache.js';
5
5
  /**
6
6
  * A test implementation of EpochCacheInterface that allows manual configuration
7
7
  * of committee, proposer, slot, and escape hatch state for use in tests.
@@ -17,6 +17,7 @@ export declare class TestEpochCache implements EpochCacheInterface {
17
17
  private seed;
18
18
  private registeredValidators;
19
19
  private l1Constants;
20
+ private proposerPipeliningEnabled;
20
21
  constructor(l1Constants?: Partial<L1RollupConstants>);
21
22
  /**
22
23
  * Sets the committee members. Used in validation and attestation flows.
@@ -54,12 +55,21 @@ export declare class TestEpochCache implements EpochCacheInterface {
54
55
  */
55
56
  setL1Constants(constants: Partial<L1RollupConstants>): this;
56
57
  getL1Constants(): L1RollupConstants;
58
+ setProposerPipeliningEnabled(enabled: boolean): void;
57
59
  getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo>;
60
+ getSlotNow(): SlotNumber;
61
+ getTargetSlot(): SlotNumber;
62
+ getEpochNow(): EpochNumber;
63
+ getTargetEpoch(): EpochNumber;
64
+ isProposerPipeliningEnabled(): boolean;
58
65
  getEpochAndSlotNow(): EpochAndSlot & {
59
66
  nowMs: bigint;
60
67
  };
61
68
  getEpochAndSlotInNextL1Slot(): EpochAndSlot & {
62
- now: bigint;
69
+ nowSeconds: bigint;
70
+ };
71
+ getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & {
72
+ nowSeconds: bigint;
63
73
  };
64
74
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
65
75
  computeProposerIndex(slot: SlotNumber, _epoch: EpochNumber, _seed: bigint, size: bigint): bigint;
@@ -67,10 +77,15 @@ export declare class TestEpochCache implements EpochCacheInterface {
67
77
  currentSlot: SlotNumber;
68
78
  nextSlot: SlotNumber;
69
79
  };
80
+ getTargetAndNextSlot(): {
81
+ targetSlot: SlotNumber;
82
+ nextSlot: SlotNumber;
83
+ };
70
84
  getProposerAttesterAddressInSlot(_slot: SlotNumber): Promise<EthAddress | undefined>;
71
85
  getRegisteredValidators(): Promise<EthAddress[]>;
72
86
  isInCommittee(_slot: SlotTag, validator: EthAddress): Promise<boolean>;
73
87
  filterInCommittee(_slot: SlotTag, validators: EthAddress[]): Promise<EthAddress[]>;
88
+ isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean>;
74
89
  isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean>;
75
90
  }
76
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3JFLE9BQU8sS0FBSyxFQUFFLFlBQVksRUFBRSxtQkFBbUIsRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsTUFBTSxtQkFBbUIsQ0FBQztBQWF4Rzs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUV2QyxZQUFZLFdBQVcsR0FBRSxPQUFPLENBQUMsaUJBQWlCLENBQU0sRUFFdkQ7SUFFRDs7O09BR0c7SUFDSCxZQUFZLENBQUMsU0FBUyxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHMUM7SUFFRDs7O09BR0c7SUFDSCxXQUFXLENBQUMsUUFBUSxFQUFFLFVBQVUsR0FBRyxTQUFTLEdBQUcsSUFBSSxDQUdsRDtJQUVEOzs7T0FHRztJQUNILGNBQWMsQ0FBQyxJQUFJLEVBQUUsVUFBVSxHQUFHLElBQUksQ0FHckM7SUFFRDs7O09BR0c7SUFDSCxrQkFBa0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxHQUFHLElBQUksQ0FHdEM7SUFFRDs7O09BR0c7SUFDSCxPQUFPLENBQUMsSUFBSSxFQUFFLE1BQU0sR0FBRyxJQUFJLENBRzFCO0lBRUQ7OztPQUdHO0lBQ0gsdUJBQXVCLENBQUMsVUFBVSxFQUFFLFVBQVUsRUFBRSxHQUFHLElBQUksQ0FHdEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsU0FBUyxFQUFFLE9BQU8sQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLElBQUksQ0FHMUQ7SUFFRCxjQUFjLElBQUksaUJBQWlCLENBRWxDO0lBRUQsWUFBWSxDQUFDLEtBQUssQ0FBQyxFQUFFLE9BQU8sR0FBRyxPQUFPLENBQUMsa0JBQWtCLENBQUMsQ0FRekQ7SUFFRCxrQkFBa0IsSUFBSSxZQUFZLEdBQUc7UUFBRSxLQUFLLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FJckQ7SUFFRCwyQkFBMkIsSUFBSSxZQUFZLEdBQUc7UUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFBO0tBQUUsQ0FPNUQ7SUFFRCx3QkFBd0IsQ0FBQyxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE1BQU0sR0FBRyxLQUFLLE1BQU0sRUFBRSxDQUcxRjtJQUVELG9CQUFvQixDQUFDLElBQUksRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFLFdBQVcsRUFBRSxLQUFLLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsTUFBTSxDQUsvRjtJQUVELHFCQUFxQixJQUFJO1FBQUUsV0FBVyxFQUFFLFVBQVUsQ0FBQztRQUFDLFFBQVEsRUFBRSxVQUFVLENBQUE7S0FBRSxDQUt6RTtJQUVELGdDQUFnQyxDQUFDLEtBQUssRUFBRSxVQUFVLEdBQUcsT0FBTyxDQUFDLFVBQVUsR0FBRyxTQUFTLENBQUMsQ0FFbkY7SUFFRCx1QkFBdUIsSUFBSSxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FFL0M7SUFFRCxhQUFhLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFckU7SUFFRCxpQkFBaUIsQ0FBQyxLQUFLLEVBQUUsT0FBTyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxPQUFPLENBQUMsVUFBVSxFQUFFLENBQUMsQ0FHakY7SUFFRCx1QkFBdUIsQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUV6RDtDQUNGIn0=
91
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoidGVzdF9lcG9jaF9jYWNoZS5kLnRzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL3Rlc3QvdGVzdF9lcG9jaF9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsV0FBVyxFQUFFLFVBQVUsRUFBRSxNQUFNLGlDQUFpQyxDQUFDO0FBQzFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEtBQUssRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZCQUE2QixDQUFDO0FBR3JFLE9BQU8sRUFDTCxLQUFLLFlBQVksRUFDakIsS0FBSyxtQkFBbUIsRUFDeEIsS0FBSyxrQkFBa0IsRUFFdkIsS0FBSyxPQUFPLEVBQ2IsTUFBTSxtQkFBbUIsQ0FBQztBQWMzQjs7Ozs7O0dBTUc7QUFDSCxxQkFBYSxjQUFlLFlBQVcsbUJBQW1CO0lBQ3hELE9BQU8sQ0FBQyxTQUFTLENBQW9CO0lBQ3JDLE9BQU8sQ0FBQyxlQUFlLENBQXlCO0lBQ2hELE9BQU8sQ0FBQyxXQUFXLENBQTZCO0lBQ2hELE9BQU8sQ0FBQyxlQUFlLENBQWtCO0lBQ3pDLE9BQU8sQ0FBQyxJQUFJLENBQWM7SUFDMUIsT0FBTyxDQUFDLG9CQUFvQixDQUFvQjtJQUNoRCxPQUFPLENBQUMsV0FBVyxDQUFvQjtJQUN2QyxPQUFPLENBQUMseUJBQXlCLENBQVM7SUFFMUMsWUFBWSxXQUFXLEdBQUUsT0FBTyxDQUFDLGlCQUFpQixDQUFNLEVBRXZEO0lBRUQ7OztPQUdHO0lBQ0gsWUFBWSxDQUFDLFNBQVMsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBRzFDO0lBRUQ7OztPQUdHO0lBQ0gsV0FBVyxDQUFDLFFBQVEsRUFBRSxVQUFVLEdBQUcsU0FBUyxHQUFHLElBQUksQ0FHbEQ7SUFFRDs7O09BR0c7SUFDSCxjQUFjLENBQUMsSUFBSSxFQUFFLFVBQVUsR0FBRyxJQUFJLENBR3JDO0lBRUQ7OztPQUdHO0lBQ0gsa0JBQWtCLENBQUMsSUFBSSxFQUFFLE9BQU8sR0FBRyxJQUFJLENBR3RDO0lBRUQ7OztPQUdHO0lBQ0gsT0FBTyxDQUFDLElBQUksRUFBRSxNQUFNLEdBQUcsSUFBSSxDQUcxQjtJQUVEOzs7T0FHRztJQUNILHVCQUF1QixDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLENBR3REO0lBRUQ7OztPQUdHO0lBQ0gsY0FBYyxDQUFDLFNBQVMsRUFBRSxPQUFPLENBQUMsaUJBQWlCLENBQUMsR0FBRyxJQUFJLENBRzFEO0lBRUQsY0FBYyxJQUFJLGlCQUFpQixDQUVsQztJQUVELDRCQUE0QixDQUFDLE9BQU8sRUFBRSxPQUFPLEdBQUcsSUFBSSxDQUVuRDtJQUVELFlBQVksQ0FBQyxLQUFLLENBQUMsRUFBRSxPQUFPLEdBQUcsT0FBTyxDQUFDLGtCQUFrQixDQUFDLENBUXpEO0lBRUQsVUFBVSxJQUFJLFVBQVUsQ0FFdkI7SUFFRCxhQUFhLElBQUksVUFBVSxDQUkxQjtJQUVELFdBQVcsSUFBSSxXQUFXLENBRXpCO0lBRUQsY0FBYyxJQUFJLFdBQVcsQ0FFNUI7SUFFRCwyQkFBMkIsSUFBSSxPQUFPLENBRXJDO0lBRUQsa0JBQWtCLElBQUksWUFBWSxHQUFHO1FBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBU3JEO0lBRUQsMkJBQTJCLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBWW5FO0lBRUQsaUNBQWlDLElBQUksWUFBWSxHQUFHO1FBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQTtLQUFFLENBS3pFO0lBRUQsd0JBQXdCLENBQUMsS0FBSyxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxNQUFNLEdBQUcsS0FBSyxNQUFNLEVBQUUsQ0FHMUY7SUFFRCxvQkFBb0IsQ0FBQyxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxXQUFXLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsTUFBTSxHQUFHLE1BQU0sQ0FLL0Y7SUFFRCxxQkFBcUIsSUFBSTtRQUFFLFdBQVcsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRekU7SUFFRCxvQkFBb0IsSUFBSTtRQUFFLFVBQVUsRUFBRSxVQUFVLENBQUM7UUFBQyxRQUFRLEVBQUUsVUFBVSxDQUFBO0tBQUUsQ0FRdkU7SUFFRCxnQ0FBZ0MsQ0FBQyxLQUFLLEVBQUUsVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLEdBQUcsU0FBUyxDQUFDLENBRW5GO0lBRUQsdUJBQXVCLElBQUksT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBRS9DO0lBRUQsYUFBYSxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXJFO0lBRUQsaUJBQWlCLENBQUMsS0FBSyxFQUFFLE9BQU8sRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLEdBQUcsT0FBTyxDQUFDLFVBQVUsRUFBRSxDQUFDLENBR2pGO0lBRUQsaUJBQWlCLENBQUMsTUFBTSxFQUFFLFdBQVcsR0FBRyxPQUFPLENBQUMsT0FBTyxDQUFDLENBRXZEO0lBRUQsdUJBQXVCLENBQUMsS0FBSyxDQUFDLEVBQUUsT0FBTyxHQUFHLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FFekQ7Q0FDRiJ9
@@ -1 +1 @@
1
- {"version":3,"file":"test_epoch_cache.d.ts","sourceRoot":"","sources":["../../src/test/test_epoch_cache.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,iCAAiC,CAAC;AAC1E,OAAO,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAGrE,OAAO,KAAK,EAAE,YAAY,EAAE,mBAAmB,EAAE,kBAAkB,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAaxG;;;;;;GAMG;AACH,qBAAa,cAAe,YAAW,mBAAmB;IACxD,OAAO,CAAC,SAAS,CAAoB;IACrC,OAAO,CAAC,eAAe,CAAyB;IAChD,OAAO,CAAC,WAAW,CAA6B;IAChD,OAAO,CAAC,eAAe,CAAkB;IACzC,OAAO,CAAC,IAAI,CAAc;IAC1B,OAAO,CAAC,oBAAoB,CAAoB;IAChD,OAAO,CAAC,WAAW,CAAoB;IAEvC,YAAY,WAAW,GAAE,OAAO,CAAC,iBAAiB,CAAM,EAEvD;IAED;;;OAGG;IACH,YAAY,CAAC,SAAS,EAAE,UAAU,EAAE,GAAG,IAAI,CAG1C;IAED;;;OAGG;IACH,WAAW,CAAC,QAAQ,EAAE,UAAU,GAAG,SAAS,GAAG,IAAI,CAGlD;IAED;;;OAGG;IACH,cAAc,CAAC,IAAI,EAAE,UAAU,GAAG,IAAI,CAGrC;IAED;;;OAGG;IACH,kBAAkB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,CAGtC;IAED;;;OAGG;IACH,OAAO,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAG1B;IAED;;;OAGG;IACH,uBAAuB,CAAC,UAAU,EAAE,UAAU,EAAE,GAAG,IAAI,CAGtD;IAED;;;OAGG;IACH,cAAc,CAAC,SAAS,EAAE,OAAO,CAAC,iBAAiB,CAAC,GAAG,IAAI,CAG1D;IAED,cAAc,IAAI,iBAAiB,CAElC;IAED,YAAY,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,kBAAkB,CAAC,CAQzD;IAED,kBAAkB,IAAI,YAAY,GAAG;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAIrD;IAED,2BAA2B,IAAI,YAAY,GAAG;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,CAO5D;IAED,wBAAwB,CAAC,KAAK,EAAE,WAAW,EAAE,IAAI,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,GAAG,KAAK,MAAM,EAAE,CAG1F;IAED,oBAAoB,CAAC,IAAI,EAAE,UAAU,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,CAK/F;IAED,qBAAqB,IAAI;QAAE,WAAW,EAAE,UAAU,CAAC;QAAC,QAAQ,EAAE,UAAU,CAAA;KAAE,CAKzE;IAED,gCAAgC,CAAC,KAAK,EAAE,UAAU,GAAG,OAAO,CAAC,UAAU,GAAG,SAAS,CAAC,CAEnF;IAED,uBAAuB,IAAI,OAAO,CAAC,UAAU,EAAE,CAAC,CAE/C;IAED,aAAa,CAAC,KAAK,EAAE,OAAO,EAAE,SAAS,EAAE,UAAU,GAAG,OAAO,CAAC,OAAO,CAAC,CAErE;IAED,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,UAAU,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC,CAGjF;IAED,uBAAuB,CAAC,KAAK,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC,CAEzD;CACF"}
1
+ {"version":3,"file":"test_epoch_cache.d.ts","sourceRoot":"","sources":["../../src/test/test_epoch_cache.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,6 @@
1
1
  import { SlotNumber } from '@aztec/foundation/branded-types';
2
2
  import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
3
+ import { PROPOSER_PIPELINING_SLOT_OFFSET } from '../epoch_cache.js';
3
4
  /** Default L1 constants for testing. */ const DEFAULT_L1_CONSTANTS = {
4
5
  l1StartBlock: 0n,
5
6
  l1GenesisTime: 0n,
@@ -7,7 +8,8 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
7
8
  epochDuration: 16,
8
9
  ethereumSlotDuration: 12,
9
10
  proofSubmissionEpochs: 2,
10
- targetCommitteeSize: 48
11
+ targetCommitteeSize: 48,
12
+ rollupManaLimit: Number.MAX_SAFE_INTEGER
11
13
  };
12
14
  /**
13
15
  * A test implementation of EpochCacheInterface that allows manual configuration
@@ -23,6 +25,7 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
23
25
  seed = 0n;
24
26
  registeredValidators = [];
25
27
  l1Constants;
28
+ proposerPipeliningEnabled = false;
26
29
  constructor(l1Constants = {}){
27
30
  this.l1Constants = {
28
31
  ...DEFAULT_L1_CONSTANTS,
@@ -84,6 +87,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
84
87
  getL1Constants() {
85
88
  return this.l1Constants;
86
89
  }
90
+ setProposerPipeliningEnabled(enabled) {
91
+ this.proposerPipeliningEnabled = enabled;
92
+ }
87
93
  getCommittee(_slot) {
88
94
  const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
89
95
  return Promise.resolve({
@@ -93,27 +99,52 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
93
99
  isEscapeHatchOpen: this.escapeHatchOpen
94
100
  });
95
101
  }
102
+ getSlotNow() {
103
+ return this.currentSlot;
104
+ }
105
+ getTargetSlot() {
106
+ return this.proposerPipeliningEnabled ? SlotNumber(this.currentSlot + PROPOSER_PIPELINING_SLOT_OFFSET) : this.currentSlot;
107
+ }
108
+ getEpochNow() {
109
+ return getEpochAtSlot(this.currentSlot, this.l1Constants);
110
+ }
111
+ getTargetEpoch() {
112
+ return getEpochAtSlot(this.getTargetSlot(), this.l1Constants);
113
+ }
114
+ isProposerPipeliningEnabled() {
115
+ return this.proposerPipeliningEnabled;
116
+ }
96
117
  getEpochAndSlotNow() {
97
- const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
98
- const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
118
+ const epochNow = getEpochAtSlot(this.currentSlot, this.l1Constants);
119
+ const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
99
120
  return {
100
- epoch,
121
+ epoch: epochNow,
101
122
  slot: this.currentSlot,
102
123
  ts,
103
124
  nowMs: ts * 1000n
104
125
  };
105
126
  }
106
127
  getEpochAndSlotInNextL1Slot() {
107
- const now = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
108
- const nextSlotTs = now + BigInt(this.l1Constants.ethereumSlotDuration);
128
+ const nowTs = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
129
+ const nextSlotTs = nowTs + BigInt(this.l1Constants.ethereumSlotDuration);
109
130
  const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
110
- const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
111
- const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
131
+ const epochNow = getEpochAtSlot(nextSlot, this.l1Constants);
132
+ const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
112
133
  return {
113
- epoch,
134
+ epoch: epochNow,
114
135
  slot: nextSlot,
115
136
  ts,
116
- now
137
+ nowSeconds: nowTs
138
+ };
139
+ }
140
+ getTargetEpochAndSlotInNextL1Slot() {
141
+ const result = this.getEpochAndSlotInNextL1Slot();
142
+ const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
143
+ const targetSlot = SlotNumber(result.slot + offset);
144
+ return {
145
+ ...result,
146
+ slot: targetSlot,
147
+ epoch: getEpochAtSlot(targetSlot, this.l1Constants)
117
148
  };
118
149
  }
119
150
  getProposerIndexEncoding(epoch, slot, seed) {
@@ -127,9 +158,19 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
127
158
  return BigInt(slot) % size;
128
159
  }
129
160
  getCurrentAndNextSlot() {
161
+ const currentSlot = this.getSlotNow();
162
+ const next = this.getEpochAndSlotInNextL1Slot();
163
+ return {
164
+ currentSlot,
165
+ nextSlot: next.slot
166
+ };
167
+ }
168
+ getTargetAndNextSlot() {
169
+ const targetSlot = this.getTargetSlot();
170
+ const next = this.getTargetEpochAndSlotInNextL1Slot();
130
171
  return {
131
- currentSlot: this.currentSlot,
132
- nextSlot: SlotNumber(this.currentSlot + 1)
172
+ targetSlot,
173
+ nextSlot: next.slot
133
174
  };
134
175
  }
135
176
  getProposerAttesterAddressInSlot(_slot) {
@@ -145,6 +186,9 @@ import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@
145
186
  const committeeSet = new Set(this.committee.map((v)=>v.toString()));
146
187
  return Promise.resolve(validators.filter((v)=>committeeSet.has(v.toString())));
147
188
  }
189
+ isEscapeHatchOpen(_epoch) {
190
+ return Promise.resolve(this.escapeHatchOpen);
191
+ }
148
192
  isEscapeHatchOpenAtSlot(_slot) {
149
193
  return Promise.resolve(this.escapeHatchOpen);
150
194
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/epoch-cache",
3
- "version": "0.0.1-commit.ef17749e1",
3
+ "version": "0.0.1-commit.f1b29a41e",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  ".": "./dest/index.js",
@@ -26,10 +26,10 @@
26
26
  "../package.common.json"
27
27
  ],
28
28
  "dependencies": {
29
- "@aztec/ethereum": "0.0.1-commit.ef17749e1",
30
- "@aztec/foundation": "0.0.1-commit.ef17749e1",
31
- "@aztec/l1-artifacts": "0.0.1-commit.ef17749e1",
32
- "@aztec/stdlib": "0.0.1-commit.ef17749e1",
29
+ "@aztec/ethereum": "0.0.1-commit.f1b29a41e",
30
+ "@aztec/foundation": "0.0.1-commit.f1b29a41e",
31
+ "@aztec/l1-artifacts": "0.0.1-commit.f1b29a41e",
32
+ "@aztec/stdlib": "0.0.1-commit.f1b29a41e",
33
33
  "dotenv": "^16.0.3",
34
34
  "get-port": "^7.1.0",
35
35
  "jest-mock-extended": "^4.0.0",
package/src/config.ts CHANGED
@@ -1,11 +1,17 @@
1
1
  import { type L1ContractsConfig, getL1ContractsConfigEnvVars } from '@aztec/ethereum/config';
2
2
  import { type L1ReaderConfig, getL1ReaderConfigFromEnv } from '@aztec/ethereum/l1-reader';
3
+ import { type PipelineConfig, getPipelineConfigEnvVars } from '@aztec/stdlib/config';
3
4
 
4
5
  export type EpochCacheConfig = Pick<
5
- L1ReaderConfig & L1ContractsConfig,
6
- 'l1RpcUrls' | 'l1ChainId' | 'viemPollingIntervalMS' | 'ethereumSlotDuration'
6
+ L1ReaderConfig & L1ContractsConfig & PipelineConfig,
7
+ | 'l1RpcUrls'
8
+ | 'l1ChainId'
9
+ | 'viemPollingIntervalMS'
10
+ | 'ethereumSlotDuration'
11
+ | 'l1HttpTimeoutMS'
12
+ | 'enableProposerPipelining'
7
13
  >;
8
14
 
9
15
  export function getEpochCacheConfigEnvVars(): EpochCacheConfig {
10
- return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars() };
16
+ return { ...getL1ReaderConfigFromEnv(), ...getL1ContractsConfigEnvVars(), ...getPipelineConfigEnvVars() };
11
17
  }
@@ -1,4 +1,5 @@
1
1
  import { createEthereumChain } from '@aztec/ethereum/chain';
2
+ import { makeL1HttpTransport } from '@aztec/ethereum/client';
2
3
  import { NoCommitteeError, RollupContract } from '@aztec/ethereum/contracts';
3
4
  import { EpochNumber, SlotNumber } from '@aztec/foundation/branded-types';
4
5
  import { EthAddress } from '@aztec/foundation/eth-address';
@@ -8,19 +9,24 @@ import {
8
9
  type L1RollupConstants,
9
10
  getEpochAtSlot,
10
11
  getEpochNumberAtTimestamp,
12
+ getNextL1SlotTimestamp,
13
+ getSlotAtNextL1Block,
11
14
  getSlotAtTimestamp,
12
15
  getSlotRangeForEpoch,
13
16
  getTimestampForSlot,
14
- getTimestampRangeForEpoch,
15
17
  } from '@aztec/stdlib/epoch-helpers';
16
18
 
17
- import { createPublicClient, encodeAbiParameters, fallback, http, keccak256 } from 'viem';
19
+ import { createPublicClient, encodeAbiParameters, keccak256 } from 'viem';
18
20
 
19
21
  import { type EpochCacheConfig, getEpochCacheConfigEnvVars } from './config.js';
20
22
 
23
+ /** When proposer pipelining is enabled, the proposer builds one slot ahead. */
24
+ export const PROPOSER_PIPELINING_SLOT_OFFSET = 1;
25
+
26
+ /** Flat return type for compound epoch/slot getters. */
21
27
  export type EpochAndSlot = {
22
- epoch: EpochNumber;
23
28
  slot: SlotNumber;
29
+ epoch: EpochNumber;
24
30
  ts: bigint;
25
31
  };
26
32
 
@@ -36,11 +42,21 @@ export type SlotTag = 'now' | 'next' | SlotNumber;
36
42
 
37
43
  export interface EpochCacheInterface {
38
44
  getCommittee(slot: SlotTag | undefined): Promise<EpochCommitteeInfo>;
45
+ getSlotNow(): SlotNumber;
46
+ getTargetSlot(): SlotNumber;
47
+ getEpochNow(): EpochNumber;
48
+ getTargetEpoch(): EpochNumber;
39
49
  getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint };
40
- getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint };
50
+ getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint };
51
+ /** Returns epoch/slot info for the next L1 slot with pipeline offset applied. */
52
+ getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint };
53
+ isProposerPipeliningEnabled(): boolean;
54
+ isEscapeHatchOpen(epoch: EpochNumber): Promise<boolean>;
55
+ isEscapeHatchOpenAtSlot(slot: SlotTag): Promise<boolean>;
41
56
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}`;
42
57
  computeProposerIndex(slot: SlotNumber, epoch: EpochNumber, seed: bigint, size: bigint): bigint;
43
58
  getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber };
59
+ getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber };
44
60
  getProposerAttesterAddressInSlot(slot: SlotNumber): Promise<EthAddress | undefined>;
45
61
  getRegisteredValidators(): Promise<EthAddress[]>;
46
62
  isInCommittee(slot: SlotTag, validator: EthAddress): Promise<boolean>;
@@ -64,6 +80,8 @@ export class EpochCache implements EpochCacheInterface {
64
80
  private lastValidatorRefresh = 0;
65
81
  private readonly log: Logger = createLogger('epoch-cache');
66
82
 
83
+ protected enableProposerPipelining: boolean;
84
+
67
85
  constructor(
68
86
  private rollup: RollupContract,
69
87
  private readonly l1constants: L1RollupConstants & {
@@ -71,10 +89,12 @@ export class EpochCache implements EpochCacheInterface {
71
89
  lagInEpochsForRandao: number;
72
90
  },
73
91
  private readonly dateProvider: DateProvider = new DateProvider(),
74
- protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60 },
92
+ protected readonly config = { cacheSize: 12, validatorRefreshIntervalSeconds: 60, enableProposerPipelining: false },
75
93
  ) {
94
+ this.enableProposerPipelining = this.config.enableProposerPipelining;
76
95
  this.log.debug(`Initialized EpochCache`, {
77
96
  l1constants,
97
+ enableProposerPipelining: this.enableProposerPipelining,
78
98
  });
79
99
  }
80
100
 
@@ -93,7 +113,7 @@ export class EpochCache implements EpochCacheInterface {
93
113
  const chain = createEthereumChain(config.l1RpcUrls, config.l1ChainId);
94
114
  const publicClient = createPublicClient({
95
115
  chain: chain.chainInfo,
96
- transport: fallback(config.l1RpcUrls.map(url => http(url, { batch: false }))),
116
+ transport: makeL1HttpTransport(config.l1RpcUrls, { timeout: config.l1HttpTimeoutMS }),
97
117
  pollingInterval: config.viemPollingIntervalMS,
98
118
  });
99
119
  rollup = new RollupContract(publicClient, rollupOrAddress.toString());
@@ -108,6 +128,7 @@ export class EpochCache implements EpochCacheInterface {
108
128
  lagInEpochsForValidatorSet,
109
129
  lagInEpochsForRandao,
110
130
  targetCommitteeSize,
131
+ rollupManaLimit,
111
132
  ] = await Promise.all([
112
133
  rollup.getL1StartBlock(),
113
134
  rollup.getL1GenesisTime(),
@@ -117,6 +138,7 @@ export class EpochCache implements EpochCacheInterface {
117
138
  rollup.getLagInEpochsForValidatorSet(),
118
139
  rollup.getLagInEpochsForRandao(),
119
140
  rollup.getTargetCommitteeSize(),
141
+ rollup.getManaLimit(),
120
142
  ] as const);
121
143
 
122
144
  const l1RollupConstants = {
@@ -129,43 +151,76 @@ export class EpochCache implements EpochCacheInterface {
129
151
  lagInEpochsForValidatorSet: Number(lagInEpochsForValidatorSet),
130
152
  lagInEpochsForRandao: Number(lagInEpochsForRandao),
131
153
  targetCommitteeSize: Number(targetCommitteeSize),
154
+ rollupManaLimit: Number(rollupManaLimit),
132
155
  };
133
156
 
134
- return new EpochCache(rollup, l1RollupConstants, deps.dateProvider);
157
+ return new EpochCache(rollup, l1RollupConstants, deps.dateProvider, {
158
+ cacheSize: 12,
159
+ validatorRefreshIntervalSeconds: 60,
160
+ enableProposerPipelining: config.enableProposerPipelining,
161
+ });
135
162
  }
136
163
 
137
164
  public getL1Constants(): L1RollupConstants {
138
165
  return this.l1constants;
139
166
  }
140
167
 
168
+ public isProposerPipeliningEnabled(): boolean {
169
+ return this.enableProposerPipelining;
170
+ }
171
+
172
+ public getSlotNow(): SlotNumber {
173
+ return this.getEpochAndSlotNow().slot;
174
+ }
175
+
176
+ public getTargetSlot(): SlotNumber {
177
+ const slotNow = this.getSlotNow();
178
+ const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
179
+ return SlotNumber(slotNow + offset);
180
+ }
181
+
182
+ public getEpochNow(): EpochNumber {
183
+ return this.getEpochAndSlotNow().epoch;
184
+ }
185
+
186
+ public getTargetEpoch(): EpochNumber {
187
+ return getEpochAtSlot(this.getTargetSlot(), this.l1constants);
188
+ }
189
+
141
190
  public getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
142
191
  const nowMs = BigInt(this.dateProvider.now());
143
192
  const nowSeconds = nowMs / 1000n;
144
193
  return { ...this.getEpochAndSlotAtTimestamp(nowSeconds), nowMs };
145
194
  }
146
195
 
147
- public nowInSeconds(): bigint {
148
- return BigInt(Math.floor(this.dateProvider.now() / 1000));
196
+ private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
197
+ return this.getEpochAndSlotAtTimestamp(getTimestampForSlot(slot, this.l1constants));
149
198
  }
150
199
 
151
- private getEpochAndSlotAtSlot(slot: SlotNumber): EpochAndSlot {
152
- const epoch = getEpochAtSlot(slot, this.l1constants);
153
- const ts = getTimestampRangeForEpoch(epoch, this.l1constants)[0];
154
- return { epoch, ts, slot };
200
+ public getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
201
+ const nowSeconds = this.dateProvider.nowInSeconds();
202
+ const nextSlotTs = getNextL1SlotTimestamp(nowSeconds, this.l1constants);
203
+ return { ...this.getEpochAndSlotAtTimestamp(nextSlotTs), nowSeconds: BigInt(nowSeconds) };
155
204
  }
156
205
 
157
- public getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint } {
158
- const now = this.nowInSeconds();
159
- const nextSlotTs = now + BigInt(this.l1constants.ethereumSlotDuration);
160
- return { ...this.getEpochAndSlotAtTimestamp(nextSlotTs), now };
206
+ public getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
207
+ if (!this.isProposerPipeliningEnabled()) {
208
+ return this.getEpochAndSlotInNextL1Slot();
209
+ }
210
+
211
+ const result = this.getEpochAndSlotInNextL1Slot();
212
+ const offset = PROPOSER_PIPELINING_SLOT_OFFSET;
213
+ const targetSlot = SlotNumber(result.slot + offset);
214
+ return { ...result, slot: targetSlot, epoch: getEpochAtSlot(targetSlot, this.l1constants) };
161
215
  }
162
216
 
163
217
  private getEpochAndSlotAtTimestamp(ts: bigint): EpochAndSlot {
164
218
  const slot = getSlotAtTimestamp(ts, this.l1constants);
219
+ const epoch = getEpochNumberAtTimestamp(ts, this.l1constants);
165
220
  return {
166
- epoch: getEpochNumberAtTimestamp(ts, this.l1constants),
167
- ts: getTimestampForSlot(slot, this.l1constants),
168
221
  slot,
222
+ epoch,
223
+ ts: getTimestampForSlot(slot, this.l1constants),
169
224
  };
170
225
  }
171
226
 
@@ -198,7 +253,7 @@ export class EpochCache implements EpochCacheInterface {
198
253
  public async isEscapeHatchOpenAtSlot(slot: SlotTag = 'now'): Promise<boolean> {
199
254
  const epoch =
200
255
  slot === 'now'
201
- ? this.getEpochAndSlotNow().epoch
256
+ ? this.getEpochNow()
202
257
  : slot === 'next'
203
258
  ? this.getEpochAndSlotInNextL1Slot().epoch
204
259
  : getEpochAtSlot(slot, this.l1constants);
@@ -233,7 +288,7 @@ export class EpochCache implements EpochCacheInterface {
233
288
  return epochData;
234
289
  }
235
290
 
236
- private getEpochAndTimestamp(slot: SlotTag = 'now') {
291
+ private getEpochAndTimestamp(slot: SlotTag = 'now'): { epoch: EpochNumber; ts: bigint } {
237
292
  if (slot === 'now') {
238
293
  return this.getEpochAndSlotNow();
239
294
  } else if (slot === 'next') {
@@ -283,17 +338,31 @@ export class EpochCache implements EpochCacheInterface {
283
338
  return BigInt(keccak256(this.getProposerIndexEncoding(epoch, slot, seed))) % size;
284
339
  }
285
340
 
286
- /** Returns the current and next L2 slot numbers. */
341
+ /** Returns the current and next L2 slot in next eth L1 Slot. */
287
342
  public getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
288
- const current = this.getEpochAndSlotNow();
343
+ const currentSlot = this.getSlotNow();
289
344
  const next = this.getEpochAndSlotInNextL1Slot();
290
345
 
291
346
  return {
292
- currentSlot: current.slot,
347
+ currentSlot,
293
348
  nextSlot: next.slot,
294
349
  };
295
350
  }
296
351
 
352
+ /** Returns the target and next L2 slot in the next L1 slot. */
353
+ public getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber } {
354
+ const nowSeconds = BigInt(this.dateProvider.nowInSeconds());
355
+ const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
356
+
357
+ const currentSlot = getSlotAtTimestamp(nowSeconds, this.l1constants);
358
+ const targetSlot = SlotNumber(currentSlot + offset);
359
+
360
+ const nextL2SlotOnL1 = getSlotAtNextL1Block(nowSeconds, this.l1constants);
361
+ const nextSlot = SlotNumber(nextL2SlotOnL1 + offset);
362
+
363
+ return { targetSlot, nextSlot };
364
+ }
365
+
297
366
  /**
298
367
  * Get the proposer attester address in the given L2 slot
299
368
  * @returns The proposer attester address. If the committee does not exist, we throw a NoCommitteeError.
@@ -372,10 +441,11 @@ export class EpochCache implements EpochCacheInterface {
372
441
  async getRegisteredValidators(): Promise<EthAddress[]> {
373
442
  const validatorRefreshIntervalMs = this.config.validatorRefreshIntervalSeconds * 1000;
374
443
  const validatorRefreshTime = this.lastValidatorRefresh + validatorRefreshIntervalMs;
375
- if (validatorRefreshTime < this.dateProvider.now()) {
376
- const currentSet = await this.rollup.getAttesters();
444
+ const now = this.dateProvider.now();
445
+ if (validatorRefreshTime < now) {
446
+ const currentSet = await this.rollup.getAttesters(BigInt(Math.floor(now / 1000)));
377
447
  this.allValidators = new Set(currentSet.map(v => v.toString()));
378
- this.lastValidatorRefresh = this.dateProvider.now();
448
+ this.lastValidatorRefresh = now;
379
449
  }
380
450
  return Array.from(this.allValidators.keys()).map(v => EthAddress.fromString(v));
381
451
  }
@@ -3,7 +3,13 @@ import { EthAddress } from '@aztec/foundation/eth-address';
3
3
  import type { L1RollupConstants } from '@aztec/stdlib/epoch-helpers';
4
4
  import { getEpochAtSlot, getSlotAtTimestamp, getTimestampRangeForEpoch } from '@aztec/stdlib/epoch-helpers';
5
5
 
6
- import type { EpochAndSlot, EpochCacheInterface, EpochCommitteeInfo, SlotTag } from '../epoch_cache.js';
6
+ import {
7
+ type EpochAndSlot,
8
+ type EpochCacheInterface,
9
+ type EpochCommitteeInfo,
10
+ PROPOSER_PIPELINING_SLOT_OFFSET,
11
+ type SlotTag,
12
+ } from '../epoch_cache.js';
7
13
 
8
14
  /** Default L1 constants for testing. */
9
15
  const DEFAULT_L1_CONSTANTS: L1RollupConstants = {
@@ -14,6 +20,7 @@ const DEFAULT_L1_CONSTANTS: L1RollupConstants = {
14
20
  ethereumSlotDuration: 12,
15
21
  proofSubmissionEpochs: 2,
16
22
  targetCommitteeSize: 48,
23
+ rollupManaLimit: Number.MAX_SAFE_INTEGER,
17
24
  };
18
25
 
19
26
  /**
@@ -31,6 +38,7 @@ export class TestEpochCache implements EpochCacheInterface {
31
38
  private seed: bigint = 0n;
32
39
  private registeredValidators: EthAddress[] = [];
33
40
  private l1Constants: L1RollupConstants;
41
+ private proposerPipeliningEnabled = false;
34
42
 
35
43
  constructor(l1Constants: Partial<L1RollupConstants> = {}) {
36
44
  this.l1Constants = { ...DEFAULT_L1_CONSTANTS, ...l1Constants };
@@ -103,6 +111,10 @@ export class TestEpochCache implements EpochCacheInterface {
103
111
  return this.l1Constants;
104
112
  }
105
113
 
114
+ setProposerPipeliningEnabled(enabled: boolean): void {
115
+ this.proposerPipeliningEnabled = enabled;
116
+ }
117
+
106
118
  getCommittee(_slot?: SlotTag): Promise<EpochCommitteeInfo> {
107
119
  const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
108
120
  return Promise.resolve({
@@ -113,19 +125,58 @@ export class TestEpochCache implements EpochCacheInterface {
113
125
  });
114
126
  }
115
127
 
128
+ getSlotNow(): SlotNumber {
129
+ return this.currentSlot;
130
+ }
131
+
132
+ getTargetSlot(): SlotNumber {
133
+ return this.proposerPipeliningEnabled
134
+ ? SlotNumber(this.currentSlot + PROPOSER_PIPELINING_SLOT_OFFSET)
135
+ : this.currentSlot;
136
+ }
137
+
138
+ getEpochNow(): EpochNumber {
139
+ return getEpochAtSlot(this.currentSlot, this.l1Constants);
140
+ }
141
+
142
+ getTargetEpoch(): EpochNumber {
143
+ return getEpochAtSlot(this.getTargetSlot(), this.l1Constants);
144
+ }
145
+
146
+ isProposerPipeliningEnabled(): boolean {
147
+ return this.proposerPipeliningEnabled;
148
+ }
149
+
116
150
  getEpochAndSlotNow(): EpochAndSlot & { nowMs: bigint } {
117
- const epoch = getEpochAtSlot(this.currentSlot, this.l1Constants);
118
- const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
119
- return { epoch, slot: this.currentSlot, ts, nowMs: ts * 1000n };
151
+ const epochNow = getEpochAtSlot(this.currentSlot, this.l1Constants);
152
+ const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
153
+ return {
154
+ epoch: epochNow,
155
+ slot: this.currentSlot,
156
+ ts,
157
+ nowMs: ts * 1000n,
158
+ };
120
159
  }
121
160
 
122
- getEpochAndSlotInNextL1Slot(): EpochAndSlot & { now: bigint } {
123
- const now = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
124
- const nextSlotTs = now + BigInt(this.l1Constants.ethereumSlotDuration);
161
+ getEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
162
+ const nowTs = getTimestampRangeForEpoch(getEpochAtSlot(this.currentSlot, this.l1Constants), this.l1Constants)[0];
163
+ const nextSlotTs = nowTs + BigInt(this.l1Constants.ethereumSlotDuration);
125
164
  const nextSlot = getSlotAtTimestamp(nextSlotTs, this.l1Constants);
126
- const epoch = getEpochAtSlot(nextSlot, this.l1Constants);
127
- const ts = getTimestampRangeForEpoch(epoch, this.l1Constants)[0];
128
- return { epoch, slot: nextSlot, ts, now };
165
+ const epochNow = getEpochAtSlot(nextSlot, this.l1Constants);
166
+ const ts = getTimestampRangeForEpoch(epochNow, this.l1Constants)[0];
167
+ return {
168
+ epoch: epochNow,
169
+ slot: nextSlot,
170
+ ts,
171
+ nowSeconds: nowTs,
172
+ };
173
+ }
174
+
175
+ getTargetEpochAndSlotInNextL1Slot(): EpochAndSlot & { nowSeconds: bigint } {
176
+ const result = this.getEpochAndSlotInNextL1Slot();
177
+ const offset = this.isProposerPipeliningEnabled() ? PROPOSER_PIPELINING_SLOT_OFFSET : 0;
178
+ const targetSlot = SlotNumber(result.slot + offset);
179
+ return { ...result, slot: targetSlot, epoch: getEpochAtSlot(targetSlot, this.l1Constants) };
129
180
  }
130
181
 
131
182
  getProposerIndexEncoding(epoch: EpochNumber, slot: SlotNumber, seed: bigint): `0x${string}` {
@@ -141,9 +192,22 @@ export class TestEpochCache implements EpochCacheInterface {
141
192
  }
142
193
 
143
194
  getCurrentAndNextSlot(): { currentSlot: SlotNumber; nextSlot: SlotNumber } {
195
+ const currentSlot = this.getSlotNow();
196
+ const next = this.getEpochAndSlotInNextL1Slot();
197
+
198
+ return {
199
+ currentSlot,
200
+ nextSlot: next.slot,
201
+ };
202
+ }
203
+
204
+ getTargetAndNextSlot(): { targetSlot: SlotNumber; nextSlot: SlotNumber } {
205
+ const targetSlot = this.getTargetSlot();
206
+ const next = this.getTargetEpochAndSlotInNextL1Slot();
207
+
144
208
  return {
145
- currentSlot: this.currentSlot,
146
- nextSlot: SlotNumber(this.currentSlot + 1),
209
+ targetSlot,
210
+ nextSlot: next.slot,
147
211
  };
148
212
  }
149
213
 
@@ -164,6 +228,10 @@ export class TestEpochCache implements EpochCacheInterface {
164
228
  return Promise.resolve(validators.filter(v => committeeSet.has(v.toString())));
165
229
  }
166
230
 
231
+ isEscapeHatchOpen(_epoch: EpochNumber): Promise<boolean> {
232
+ return Promise.resolve(this.escapeHatchOpen);
233
+ }
234
+
167
235
  isEscapeHatchOpenAtSlot(_slot?: SlotTag): Promise<boolean> {
168
236
  return Promise.resolve(this.escapeHatchOpen);
169
237
  }