@aztec/sequencer-client 0.73.0 → 0.75.0-commit.c03ba01a2a4122e43e90d5133ba017e54b90e9d2

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.
Files changed (88) hide show
  1. package/dest/client/index.js +0 -1
  2. package/dest/client/sequencer-client.js +55 -55
  3. package/dest/config.js +40 -42
  4. package/dest/global_variable_builder/global_builder.js +39 -26
  5. package/dest/global_variable_builder/index.js +0 -1
  6. package/dest/index.js +0 -1
  7. package/dest/publisher/config.js +49 -50
  8. package/dest/publisher/index.js +0 -1
  9. package/dest/publisher/sequencer-publisher-metrics.js +32 -23
  10. package/dest/publisher/sequencer-publisher.js +251 -253
  11. package/dest/sequencer/allowed.js +5 -12
  12. package/dest/sequencer/config.js +1 -2
  13. package/dest/sequencer/index.js +0 -1
  14. package/dest/sequencer/metrics.js +26 -18
  15. package/dest/sequencer/sequencer.js +648 -607
  16. package/dest/sequencer/timetable.js +33 -19
  17. package/dest/sequencer/utils.js +22 -32
  18. package/dest/slasher/factory.js +6 -5
  19. package/dest/slasher/index.js +0 -1
  20. package/dest/slasher/slasher_client.js +128 -122
  21. package/dest/test/index.js +4 -1
  22. package/dest/tx_validator/archive_cache.js +7 -7
  23. package/dest/tx_validator/gas_validator.js +76 -64
  24. package/dest/tx_validator/nullifier_cache.js +8 -8
  25. package/dest/tx_validator/phases_validator.js +27 -19
  26. package/dest/tx_validator/test_utils.js +1 -2
  27. package/dest/tx_validator/tx_validator_factory.js +5 -5
  28. package/package.json +23 -22
  29. package/src/client/sequencer-client.ts +23 -2
  30. package/src/config.ts +1 -1
  31. package/src/publisher/sequencer-publisher.ts +71 -91
  32. package/src/sequencer/sequencer.ts +29 -13
  33. package/src/slasher/factory.ts +3 -3
  34. package/src/slasher/slasher_client.ts +40 -31
  35. package/dest/client/index.d.ts +0 -2
  36. package/dest/client/index.d.ts.map +0 -1
  37. package/dest/client/sequencer-client.d.ts +0 -68
  38. package/dest/client/sequencer-client.d.ts.map +0 -1
  39. package/dest/config.d.ts +0 -37
  40. package/dest/config.d.ts.map +0 -1
  41. package/dest/global_variable_builder/global_builder.d.ts +0 -29
  42. package/dest/global_variable_builder/global_builder.d.ts.map +0 -1
  43. package/dest/global_variable_builder/index.d.ts +0 -2
  44. package/dest/global_variable_builder/index.d.ts.map +0 -1
  45. package/dest/index.d.ts +0 -8
  46. package/dest/index.d.ts.map +0 -1
  47. package/dest/publisher/config.d.ts +0 -38
  48. package/dest/publisher/config.d.ts.map +0 -1
  49. package/dest/publisher/index.d.ts +0 -2
  50. package/dest/publisher/index.d.ts.map +0 -1
  51. package/dest/publisher/sequencer-publisher-metrics.d.ts +0 -24
  52. package/dest/publisher/sequencer-publisher-metrics.d.ts.map +0 -1
  53. package/dest/publisher/sequencer-publisher.d.ts +0 -158
  54. package/dest/publisher/sequencer-publisher.d.ts.map +0 -1
  55. package/dest/sequencer/allowed.d.ts +0 -3
  56. package/dest/sequencer/allowed.d.ts.map +0 -1
  57. package/dest/sequencer/config.d.ts +0 -2
  58. package/dest/sequencer/config.d.ts.map +0 -1
  59. package/dest/sequencer/index.d.ts +0 -4
  60. package/dest/sequencer/index.d.ts.map +0 -1
  61. package/dest/sequencer/metrics.d.ts +0 -24
  62. package/dest/sequencer/metrics.d.ts.map +0 -1
  63. package/dest/sequencer/sequencer.d.ts +0 -172
  64. package/dest/sequencer/sequencer.d.ts.map +0 -1
  65. package/dest/sequencer/timetable.d.ts +0 -38
  66. package/dest/sequencer/timetable.d.ts.map +0 -1
  67. package/dest/sequencer/utils.d.ts +0 -47
  68. package/dest/sequencer/utils.d.ts.map +0 -1
  69. package/dest/slasher/factory.d.ts +0 -11
  70. package/dest/slasher/factory.d.ts.map +0 -1
  71. package/dest/slasher/index.d.ts +0 -3
  72. package/dest/slasher/index.d.ts.map +0 -1
  73. package/dest/slasher/slasher_client.d.ts +0 -127
  74. package/dest/slasher/slasher_client.d.ts.map +0 -1
  75. package/dest/test/index.d.ts +0 -17
  76. package/dest/test/index.d.ts.map +0 -1
  77. package/dest/tx_validator/archive_cache.d.ts +0 -14
  78. package/dest/tx_validator/archive_cache.d.ts.map +0 -1
  79. package/dest/tx_validator/gas_validator.d.ts +0 -12
  80. package/dest/tx_validator/gas_validator.d.ts.map +0 -1
  81. package/dest/tx_validator/nullifier_cache.d.ts +0 -16
  82. package/dest/tx_validator/nullifier_cache.d.ts.map +0 -1
  83. package/dest/tx_validator/phases_validator.d.ts +0 -11
  84. package/dest/tx_validator/phases_validator.d.ts.map +0 -1
  85. package/dest/tx_validator/test_utils.d.ts +0 -21
  86. package/dest/tx_validator/test_utils.d.ts.map +0 -1
  87. package/dest/tx_validator/tx_validator_factory.d.ts +0 -16
  88. package/dest/tx_validator/tx_validator_factory.d.ts.map +0 -1
@@ -1,21 +1,20 @@
1
- import { L2BlockStream, } from '@aztec/circuit-types';
1
+ import { L2BlockStream } from '@aztec/circuit-types';
2
2
  import { INITIAL_L2_BLOCK_NUM } from '@aztec/circuits.js/constants';
3
3
  import { createEthereumChain } from '@aztec/ethereum';
4
4
  import { EthAddress } from '@aztec/foundation/eth-address';
5
5
  import { createLogger } from '@aztec/foundation/log';
6
6
  import { SlashFactoryAbi } from '@aztec/l1-artifacts';
7
7
  import { WithTracer, getTelemetryClient } from '@aztec/telemetry-client';
8
- import { createPublicClient, getAddress, getContract, http, } from 'viem';
8
+ import { createPublicClient, getAddress, getContract, http } from 'viem';
9
9
  /**
10
10
  * Enum defining the possible states of the Slasher client.
11
- */
12
- export var SlasherClientState;
13
- (function (SlasherClientState) {
11
+ */ export var SlasherClientState = /*#__PURE__*/ function(SlasherClientState) {
14
12
  SlasherClientState[SlasherClientState["IDLE"] = 0] = "IDLE";
15
13
  SlasherClientState[SlasherClientState["SYNCHING"] = 1] = "SYNCHING";
16
14
  SlasherClientState[SlasherClientState["RUNNING"] = 2] = "RUNNING";
17
15
  SlasherClientState[SlasherClientState["STOPPED"] = 3] = "STOPPED";
18
- })(SlasherClientState || (SlasherClientState = {}));
16
+ return SlasherClientState;
17
+ }({});
19
18
  /**
20
19
  * @notice A Hypomeiones slasher client implementation
21
20
  *
@@ -40,28 +39,31 @@ export var SlasherClientState;
40
39
  * - Decide how to deal with multiple slashing events in the same round.
41
40
  * - This could be that multiple epochs are pruned in the same round, but with the current naive implementation we could end up
42
41
  * slashing only the first, because the "lifetime" of the second would have passed after that vote
43
- */
44
- export class SlasherClient extends WithTracer {
45
- constructor(config, store, l2BlockSource, telemetry = getTelemetryClient(), log = createLogger('slasher')) {
46
- super(telemetry, 'slasher');
47
- this.config = config;
48
- this.store = store;
49
- this.l2BlockSource = l2BlockSource;
50
- this.log = log;
51
- this.currentState = SlasherClientState.IDLE;
52
- this.syncPromise = Promise.resolve();
53
- this.syncResolve = undefined;
54
- this.latestBlockNumberAtStart = -1;
55
- this.provenBlockNumberAtStart = -1;
56
- this.slashEvents = [];
57
- this.slashFactoryContract = undefined;
58
- // The amount to slash for a prune.
59
- // Note that we set it to 0, such that no actual slashing will happen, but the event will be fired,
60
- // showing that the slashing mechanism is working.
61
- this.slashingAmount = 0n;
42
+ */ export class SlasherClient extends WithTracer {
43
+ config;
44
+ store;
45
+ l2BlockSource;
46
+ log;
47
+ currentState;
48
+ syncPromise;
49
+ syncResolve;
50
+ latestBlockNumberAtStart;
51
+ provenBlockNumberAtStart;
52
+ synchedBlockHashes;
53
+ synchedLatestBlockNumber;
54
+ synchedProvenBlockNumber;
55
+ blockStream;
56
+ slashEvents;
57
+ slashFactoryContract;
58
+ // The amount to slash for a prune.
59
+ // Note that we set it to 0, such that no actual slashing will happen, but the event will be fired,
60
+ // showing that the slashing mechanism is working.
61
+ slashingAmount;
62
+ constructor(config, store, l2BlockSource, telemetry = getTelemetryClient(), log = createLogger('slasher')){
63
+ super(telemetry, 'slasher'), this.config = config, this.store = store, this.l2BlockSource = l2BlockSource, this.log = log, this.currentState = 0, this.syncPromise = Promise.resolve(), this.syncResolve = undefined, this.latestBlockNumberAtStart = -1, this.provenBlockNumberAtStart = -1, this.slashEvents = [], this.slashFactoryContract = undefined, this.slashingAmount = 0n;
62
64
  this.blockStream = new L2BlockStream(l2BlockSource, this, this, createLogger('slasher:block_stream'), {
63
65
  batchSize: config.blockRequestBatchSize,
64
- pollIntervalMS: config.blockCheckIntervalMS,
66
+ pollIntervalMS: config.blockCheckIntervalMS
65
67
  });
66
68
  this.synchedBlockHashes = store.openMap('slasher_block_hashes');
67
69
  this.synchedLatestBlockNumber = store.openSingleton('slasher_last_l2_block');
@@ -71,15 +73,14 @@ export class SlasherClient extends WithTracer {
71
73
  const publicClient = createPublicClient({
72
74
  chain: chain.chainInfo,
73
75
  transport: http(chain.rpcUrl),
74
- pollingInterval: config.viemPollingIntervalMS,
76
+ pollingInterval: config.viemPollingIntervalMS
75
77
  });
76
78
  this.slashFactoryContract = getContract({
77
79
  address: getAddress(config.l1Contracts.slashFactoryAddress.toString()),
78
80
  abi: SlashFactoryAbi,
79
- client: publicClient,
81
+ client: publicClient
80
82
  });
81
- }
82
- else {
83
+ } else {
83
84
  this.log.warn('No slash factory address found, slashing will not be enabled');
84
85
  }
85
86
  this.log.info(`Slasher client initialized`);
@@ -91,7 +92,7 @@ export class SlasherClient extends WithTracer {
91
92
  }
92
93
  // As long as the slot is greater than the lifetime, we want to keep deleting the first element
93
94
  // since it will not make sense to include anymore.
94
- while (this.slashEvents.length > 0 && this.slashEvents[0].lifetime < slotNumber) {
95
+ while(this.slashEvents.length > 0 && this.slashEvents[0].lifetime < slotNumber){
95
96
  this.slashEvents.shift();
96
97
  }
97
98
  if (this.slashEvents.length == 0) {
@@ -100,7 +101,7 @@ export class SlasherClient extends WithTracer {
100
101
  const slashEvent = this.slashEvents[0];
101
102
  const [payloadAddress, isDeployed] = await this.slashFactoryContract.read.getAddressAndIsDeployed([
102
103
  slashEvent.epoch,
103
- slashEvent.amount,
104
+ slashEvent.amount
104
105
  ]);
105
106
  if (!isDeployed) {
106
107
  // The proposal cannot be executed until it is deployed
@@ -109,80 +110,89 @@ export class SlasherClient extends WithTracer {
109
110
  return EthAddress.fromString(payloadAddress);
110
111
  }
111
112
  getL2BlockHash(number) {
112
- return Promise.resolve(this.synchedBlockHashes.get(number));
113
+ return this.synchedBlockHashes.getAsync(number);
113
114
  }
114
- getL2Tips() {
115
- const latestBlockNumber = this.getSyncedLatestBlockNum();
115
+ async getL2Tips() {
116
+ const latestBlockNumber = await this.getSyncedLatestBlockNum();
116
117
  let latestBlockHash;
117
- const provenBlockNumber = this.getSyncedProvenBlockNum();
118
+ const provenBlockNumber = await this.getSyncedProvenBlockNum();
118
119
  let provenBlockHash;
119
120
  if (latestBlockNumber > 0) {
120
- latestBlockHash = this.synchedBlockHashes.get(latestBlockNumber);
121
+ latestBlockHash = await this.synchedBlockHashes.getAsync(latestBlockNumber);
121
122
  if (typeof latestBlockHash === 'undefined') {
122
123
  this.log.warn(`Block hash for latest block ${latestBlockNumber} not found`);
123
124
  throw new Error();
124
125
  }
125
126
  }
126
127
  if (provenBlockNumber > 0) {
127
- provenBlockHash = this.synchedBlockHashes.get(provenBlockNumber);
128
+ provenBlockHash = await this.synchedBlockHashes.getAsync(provenBlockNumber);
128
129
  if (typeof provenBlockHash === 'undefined') {
129
130
  this.log.warn(`Block hash for proven block ${provenBlockNumber} not found`);
130
131
  throw new Error();
131
132
  }
132
133
  }
133
134
  return Promise.resolve({
134
- latest: { hash: latestBlockHash, number: latestBlockNumber },
135
- proven: { hash: provenBlockHash, number: provenBlockNumber },
136
- finalized: { hash: provenBlockHash, number: provenBlockNumber },
135
+ latest: {
136
+ hash: latestBlockHash,
137
+ number: latestBlockNumber
138
+ },
139
+ proven: {
140
+ hash: provenBlockHash,
141
+ number: provenBlockNumber
142
+ },
143
+ finalized: {
144
+ hash: provenBlockHash,
145
+ number: provenBlockNumber
146
+ }
137
147
  });
138
148
  }
139
149
  async handleBlockStreamEvent(event) {
140
150
  this.log.debug(`Handling block stream event ${event.type}`);
141
- switch (event.type) {
151
+ switch(event.type){
142
152
  case 'blocks-added':
143
153
  await this.handleLatestL2Blocks(event.blocks);
144
154
  break;
145
155
  case 'chain-finalized':
146
- // TODO (alexg): I think we can prune the block hashes map here
147
156
  break;
148
- case 'chain-proven': {
149
- const from = this.getSyncedProvenBlockNum() + 1;
150
- const limit = event.blockNumber - from + 1;
151
- await this.handleProvenL2Blocks(await this.l2BlockSource.getBlocks(from, limit));
152
- break;
153
- }
157
+ case 'chain-proven':
158
+ {
159
+ const from = await this.getSyncedProvenBlockNum() + 1;
160
+ const limit = event.blockNumber - from + 1;
161
+ await this.handleProvenL2Blocks(await this.l2BlockSource.getBlocks(from, limit));
162
+ break;
163
+ }
154
164
  case 'chain-pruned':
155
165
  await this.handlePruneL2Blocks(event.blockNumber);
156
166
  break;
157
- default: {
158
- const _ = event;
159
- break;
160
- }
167
+ default:
168
+ {
169
+ const _ = event;
170
+ break;
171
+ }
161
172
  }
162
173
  }
163
174
  async start() {
164
- if (this.currentState === SlasherClientState.STOPPED) {
175
+ if (this.currentState === 3) {
165
176
  throw new Error('Slasher already stopped');
166
177
  }
167
- if (this.currentState !== SlasherClientState.IDLE) {
178
+ if (this.currentState !== 0) {
168
179
  return this.syncPromise;
169
180
  }
170
181
  // get the current latest block numbers
171
182
  this.latestBlockNumberAtStart = await this.l2BlockSource.getBlockNumber();
172
183
  this.provenBlockNumberAtStart = await this.l2BlockSource.getProvenBlockNumber();
173
- const syncedLatestBlock = this.getSyncedLatestBlockNum() + 1;
174
- const syncedProvenBlock = this.getSyncedProvenBlockNum() + 1;
184
+ const syncedLatestBlock = await this.getSyncedLatestBlockNum() + 1;
185
+ const syncedProvenBlock = await this.getSyncedProvenBlockNum() + 1;
175
186
  // if there are blocks to be retrieved, go to a synching state
176
187
  if (syncedLatestBlock <= this.latestBlockNumberAtStart || syncedProvenBlock <= this.provenBlockNumberAtStart) {
177
- this.setCurrentState(SlasherClientState.SYNCHING);
178
- this.syncPromise = new Promise(resolve => {
188
+ this.setCurrentState(1);
189
+ this.syncPromise = new Promise((resolve)=>{
179
190
  this.syncResolve = resolve;
180
191
  });
181
192
  this.log.verbose(`Starting sync from ${syncedLatestBlock} (last proven ${syncedProvenBlock})`);
182
- }
183
- else {
193
+ } else {
184
194
  // if no blocks to be retrieved, go straight to running
185
- this.setCurrentState(SlasherClientState.RUNNING);
195
+ this.setCurrentState(2);
186
196
  this.syncPromise = Promise.resolve();
187
197
  this.log.verbose(`Block ${syncedLatestBlock} (proven ${syncedProvenBlock}) already beyond current block`);
188
198
  }
@@ -191,82 +201,78 @@ export class SlasherClient extends WithTracer {
191
201
  return this.syncPromise;
192
202
  }
193
203
  /**
194
- * Allows consumers to stop the instance of the slasher client.
195
- * 'ready' will now return 'false' and the running promise that keeps the client synced is interrupted.
196
- */
197
- async stop() {
204
+ * Allows consumers to stop the instance of the slasher client.
205
+ * 'ready' will now return 'false' and the running promise that keeps the client synced is interrupted.
206
+ */ async stop() {
198
207
  this.log.debug('Stopping Slasher client...');
199
208
  await this.blockStream.stop();
200
209
  this.log.debug('Stopped block downloader');
201
- this.setCurrentState(SlasherClientState.STOPPED);
210
+ await this.store.close();
211
+ this.log.debug('Stopped slasher store');
212
+ this.setCurrentState(3);
202
213
  this.log.info('Slasher client stopped.');
203
214
  }
204
215
  /**
205
- * Public function to check if the slasher client is fully synced and ready to receive txs.
206
- * @returns True if the slasher client is ready to receive txs.
207
- */
208
- isReady() {
209
- return this.currentState === SlasherClientState.RUNNING;
216
+ * Public function to check if the slasher client is fully synced and ready to receive txs.
217
+ * @returns True if the slasher client is ready to receive txs.
218
+ */ isReady() {
219
+ return this.currentState === 2;
210
220
  }
211
221
  /**
212
- * Public function to check the latest block number that the slasher client is synced to.
213
- * @returns Block number of latest L2 Block we've synced with.
214
- */
215
- getSyncedLatestBlockNum() {
216
- return this.synchedLatestBlockNumber.get() ?? INITIAL_L2_BLOCK_NUM - 1;
222
+ * Public function to check the latest block number that the slasher client is synced to.
223
+ * @returns Block number of latest L2 Block we've synced with.
224
+ */ async getSyncedLatestBlockNum() {
225
+ return await this.synchedLatestBlockNumber.getAsync() ?? INITIAL_L2_BLOCK_NUM - 1;
217
226
  }
218
227
  /**
219
- * Public function to check the latest proven block number that the slasher client is synced to.
220
- * @returns Block number of latest proven L2 Block we've synced with.
221
- */
222
- getSyncedProvenBlockNum() {
223
- return this.synchedProvenBlockNumber.get() ?? INITIAL_L2_BLOCK_NUM - 1;
228
+ * Public function to check the latest proven block number that the slasher client is synced to.
229
+ * @returns Block number of latest proven L2 Block we've synced with.
230
+ */ async getSyncedProvenBlockNum() {
231
+ return await this.synchedProvenBlockNumber.getAsync() ?? INITIAL_L2_BLOCK_NUM - 1;
224
232
  }
225
233
  /**
226
- * Method to check the status of the slasher client.
227
- * @returns Information about slasher client status: state & syncedToBlockNum.
228
- */
229
- async getStatus() {
230
- const blockNumber = this.getSyncedLatestBlockNum();
231
- const blockHash = blockNumber == 0
232
- ? ''
233
- : await this.l2BlockSource
234
- .getBlockHeader(blockNumber)
235
- .then(header => header?.hash())
236
- .then(hash => hash?.toString());
234
+ * Method to check the status of the slasher client.
235
+ * @returns Information about slasher client status: state & syncedToBlockNum.
236
+ */ async getStatus() {
237
+ const blockNumber = await this.getSyncedLatestBlockNum();
238
+ const blockHash = blockNumber == 0 ? '' : await this.l2BlockSource.getBlockHeader(blockNumber).then((header)=>header?.hash()).then((hash)=>hash?.toString());
237
239
  return Promise.resolve({
238
240
  state: this.currentState,
239
- syncedToL2Block: { number: blockNumber, hash: blockHash },
241
+ syncedToL2Block: {
242
+ number: blockNumber,
243
+ hash: blockHash
244
+ }
240
245
  });
241
246
  }
242
247
  /**
243
- * Handles new blocks
244
- * @param blocks - A list of blocks that the slasher client needs to store block hashes for
245
- * @returns Empty promise.
246
- */
247
- async handleLatestL2Blocks(blocks) {
248
+ * Handles new blocks
249
+ * @param blocks - A list of blocks that the slasher client needs to store block hashes for
250
+ * @returns Empty promise.
251
+ */ async handleLatestL2Blocks(blocks) {
248
252
  if (!blocks.length) {
249
- return Promise.resolve();
253
+ return;
250
254
  }
251
- const lastBlockNum = blocks[blocks.length - 1].number;
252
- await Promise.all(blocks.map(async (block) => this.synchedBlockHashes.set(block.number, (await block.hash()).toString())));
253
- await this.synchedLatestBlockNumber.set(lastBlockNum);
254
- this.log.debug(`Synched to latest block ${lastBlockNum}`);
255
- this.startServiceIfSynched();
255
+ await this.store.transactionAsync(async ()=>{
256
+ for (const block of blocks){
257
+ await this.synchedBlockHashes.set(block.number, (await block.hash()).toString());
258
+ }
259
+ const lastBlockNum = blocks[blocks.length - 1].number;
260
+ await this.synchedLatestBlockNumber.set(lastBlockNum);
261
+ });
262
+ await this.startServiceIfSynched();
256
263
  }
257
264
  /**
258
- * Handles new proven blocks by updating the proven block number
259
- * @param blocks - A list of proven L2 blocks.
260
- * @returns Empty promise.
261
- */
262
- async handleProvenL2Blocks(blocks) {
265
+ * Handles new proven blocks by updating the proven block number
266
+ * @param blocks - A list of proven L2 blocks.
267
+ * @returns Empty promise.
268
+ */ async handleProvenL2Blocks(blocks) {
263
269
  if (!blocks.length) {
264
270
  return Promise.resolve();
265
271
  }
266
272
  const lastBlockNum = blocks[blocks.length - 1].number;
267
273
  await this.synchedProvenBlockNumber.set(lastBlockNum);
268
274
  this.log.debug(`Synched to proven block ${lastBlockNum}`);
269
- this.startServiceIfSynched();
275
+ await this.startServiceIfSynched();
270
276
  }
271
277
  async handlePruneL2Blocks(latestBlock) {
272
278
  const blockHeader = await this.l2BlockSource.getBlockHeader(latestBlock);
@@ -280,28 +286,28 @@ export class SlasherClient extends WithTracer {
280
286
  this.slashEvents.push({
281
287
  epoch: epochNumber,
282
288
  amount: this.slashingAmount,
283
- lifetime,
289
+ lifetime
284
290
  });
285
291
  await this.synchedLatestBlockNumber.set(latestBlock);
286
292
  }
287
- startServiceIfSynched() {
288
- if (this.currentState === SlasherClientState.SYNCHING &&
289
- this.getSyncedLatestBlockNum() >= this.latestBlockNumberAtStart &&
290
- this.getSyncedProvenBlockNum() >= this.provenBlockNumberAtStart) {
293
+ async startServiceIfSynched() {
294
+ const [latestBlock, provenBlock] = await Promise.all([
295
+ this.getSyncedLatestBlockNum(),
296
+ this.getSyncedProvenBlockNum()
297
+ ]);
298
+ if (this.currentState === 1 && latestBlock >= this.latestBlockNumberAtStart && provenBlock >= this.provenBlockNumberAtStart) {
291
299
  this.log.debug(`Synched to blocks at start`);
292
- this.setCurrentState(SlasherClientState.RUNNING);
300
+ this.setCurrentState(2);
293
301
  if (this.syncResolve !== undefined) {
294
302
  this.syncResolve();
295
303
  }
296
304
  }
297
305
  }
298
306
  /**
299
- * Method to set the value of the current state.
300
- * @param newState - New state value.
301
- */
302
- setCurrentState(newState) {
307
+ * Method to set the value of the current state.
308
+ * @param newState - New state value.
309
+ */ setCurrentState(newState) {
303
310
  this.currentState = newState;
304
311
  this.log.debug(`Moved to state ${SlasherClientState[this.currentState]}`);
305
312
  }
306
313
  }
307
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoic2xhc2hlcl9jbGllbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvc2xhc2hlci9zbGFzaGVyX2NsaWVudC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBSUwsYUFBYSxHQUdkLE1BQU0sc0JBQXNCLENBQUM7QUFDOUIsT0FBTyxFQUFFLG9CQUFvQixFQUFFLE1BQU0sOEJBQThCLENBQUM7QUFDcEUsT0FBTyxFQUErQyxtQkFBbUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ25HLE9BQU8sRUFBRSxVQUFVLEVBQUUsTUFBTSwrQkFBK0IsQ0FBQztBQUMzRCxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFFckQsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBd0IsVUFBVSxFQUFFLGtCQUFrQixFQUFFLE1BQU0seUJBQXlCLENBQUM7QUFFL0YsT0FBTyxFQUtMLGtCQUFrQixFQUNsQixVQUFVLEVBQ1YsV0FBVyxFQUNYLElBQUksR0FDTCxNQUFNLE1BQU0sQ0FBQztBQUVkOztHQUVHO0FBQ0gsTUFBTSxDQUFOLElBQVksa0JBS1g7QUFMRCxXQUFZLGtCQUFrQjtJQUM1QiwyREFBSSxDQUFBO0lBQ0osbUVBQVEsQ0FBQTtJQUNSLGlFQUFPLENBQUE7SUFDUCxpRUFBTyxDQUFBO0FBQ1QsQ0FBQyxFQUxXLGtCQUFrQixLQUFsQixrQkFBa0IsUUFLN0I7QUEyQkQ7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztHQXdCRztBQUNILE1BQU0sT0FBTyxhQUFjLFNBQVEsVUFBVTtJQXVCM0MsWUFDVSxNQUEwRCxFQUMxRCxLQUFtQixFQUNuQixhQUE0QixFQUNwQyxZQUE2QixrQkFBa0IsRUFBRSxFQUN6QyxNQUFNLFlBQVksQ0FBQyxTQUFTLENBQUM7UUFFckMsS0FBSyxDQUFDLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQztRQU5wQixXQUFNLEdBQU4s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
@@ -1,7 +1,10 @@
1
1
  import { SequencerClient } from '../client/sequencer-client.js';
2
2
  import { Sequencer } from '../sequencer/sequencer.js';
3
3
  class TestSequencer_ extends Sequencer {
4
+ publicProcessorFactory;
5
+ timetable;
6
+ publisher;
4
7
  }
5
8
  class TestSequencerClient_ extends SequencerClient {
9
+ sequencer;
6
10
  }
7
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvdGVzdC9pbmRleC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFFQSxPQUFPLEVBQUUsZUFBZSxFQUFFLE1BQU0sK0JBQStCLENBQUM7QUFFaEUsT0FBTyxFQUFFLFNBQVMsRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBR3RELE1BQU0sY0FBZSxTQUFRLFNBQVM7Q0FJckM7QUFJRCxNQUFNLG9CQUFxQixTQUFRLGVBQWU7Q0FFakQifQ==
@@ -2,21 +2,21 @@ import { MerkleTreeId } from '@aztec/circuit-types';
2
2
  /**
3
3
  * Implements an archive source by checking a DB and an in-memory collection.
4
4
  * Intended for validating transactions as they are added to a block.
5
- */
6
- export class ArchiveCache {
7
- constructor(db) {
5
+ */ export class ArchiveCache {
6
+ db;
7
+ archives;
8
+ constructor(db){
8
9
  this.db = db;
9
10
  this.archives = new Map();
10
11
  }
11
12
  async getArchiveIndices(archives) {
12
- const toCheckDb = archives.filter(n => !this.archives.has(n.toString()));
13
+ const toCheckDb = archives.filter((n)=>!this.archives.has(n.toString()));
13
14
  const dbHits = await this.db.findLeafIndices(MerkleTreeId.ARCHIVE, toCheckDb);
14
- dbHits.forEach((x, index) => {
15
+ dbHits.forEach((x, index)=>{
15
16
  if (x !== undefined) {
16
17
  this.archives.set(toCheckDb[index].toString(), x);
17
18
  }
18
19
  });
19
- return archives.map(n => this.archives.get(n.toString()));
20
+ return archives.map((n)=>this.archives.get(n.toString()));
20
21
  }
21
22
  }
22
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYXJjaGl2ZV9jYWNoZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eF92YWxpZGF0b3IvYXJjaGl2ZV9jYWNoZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsWUFBWSxFQUFpQyxNQUFNLHNCQUFzQixDQUFDO0FBSW5GOzs7R0FHRztBQUNILE1BQU0sT0FBTyxZQUFZO0lBR3ZCLFlBQW9CLEVBQTRCO1FBQTVCLE9BQUUsR0FBRixFQUFFLENBQTBCO1FBQzlDLElBQUksQ0FBQyxRQUFRLEdBQUcsSUFBSSxHQUFHLEVBQWtCLENBQUM7SUFDNUMsQ0FBQztJQUVNLEtBQUssQ0FBQyxpQkFBaUIsQ0FBQyxRQUFjO1FBQzNDLE1BQU0sU0FBUyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFDLENBQUM7UUFDekUsTUFBTSxNQUFNLEdBQUcsTUFBTSxJQUFJLENBQUMsRUFBRSxDQUFDLGVBQWUsQ0FBQyxZQUFZLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDO1FBQzlFLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLEVBQUUsS0FBSyxFQUFFLEVBQUU7WUFDMUIsSUFBSSxDQUFDLEtBQUssU0FBUyxFQUFFLENBQUM7Z0JBQ3BCLElBQUksQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLFNBQVMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxRQUFRLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQztZQUNwRCxDQUFDO1FBQ0gsQ0FBQyxDQUFDLENBQUM7UUFFSCxPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO0lBQzVELENBQUM7Q0FDRiJ9
@@ -1,78 +1,90 @@
1
- var _GasTxValidator_instances, _GasTxValidator_log, _GasTxValidator_publicDataSource, _GasTxValidator_feeJuiceAddress, _GasTxValidator_enforceFees, _GasTxValidator_gasFees, _GasTxValidator_shouldSkip, _GasTxValidator_validateTxFee;
2
- import { __classPrivateFieldGet, __classPrivateFieldSet } from "tslib";
3
1
  import { TxExecutionPhase } from '@aztec/circuit-types';
4
2
  import { Fr, FunctionSelector } from '@aztec/circuits.js';
5
3
  import { U128 } from '@aztec/foundation/abi';
6
4
  import { createLogger } from '@aztec/foundation/log';
7
5
  import { computeFeePayerBalanceStorageSlot, getExecutionRequestsByPhase } from '@aztec/simulator/server';
8
6
  export class GasTxValidator {
9
- constructor(publicDataSource, feeJuiceAddress, enforceFees, gasFees) {
10
- _GasTxValidator_instances.add(this);
11
- _GasTxValidator_log.set(this, createLogger('sequencer:tx_validator:tx_gas'));
12
- _GasTxValidator_publicDataSource.set(this, void 0);
13
- _GasTxValidator_feeJuiceAddress.set(this, void 0);
14
- _GasTxValidator_enforceFees.set(this, void 0);
15
- _GasTxValidator_gasFees.set(this, void 0);
16
- __classPrivateFieldSet(this, _GasTxValidator_publicDataSource, publicDataSource, "f");
17
- __classPrivateFieldSet(this, _GasTxValidator_feeJuiceAddress, feeJuiceAddress, "f");
18
- __classPrivateFieldSet(this, _GasTxValidator_enforceFees, enforceFees, "f");
19
- __classPrivateFieldSet(this, _GasTxValidator_gasFees, gasFees, "f");
7
+ #log = createLogger('sequencer:tx_validator:tx_gas');
8
+ #publicDataSource;
9
+ #feeJuiceAddress;
10
+ #enforceFees;
11
+ #gasFees;
12
+ constructor(publicDataSource, feeJuiceAddress, enforceFees, gasFees){
13
+ this.#publicDataSource = publicDataSource;
14
+ this.#feeJuiceAddress = feeJuiceAddress;
15
+ this.#enforceFees = enforceFees;
16
+ this.#gasFees = gasFees;
20
17
  }
21
18
  validateTx(tx) {
22
- if (__classPrivateFieldGet(this, _GasTxValidator_instances, "m", _GasTxValidator_shouldSkip).call(this, tx)) {
23
- return Promise.resolve({ result: 'skipped', reason: ['Insufficient fee per gas'] });
19
+ if (this.#shouldSkip(tx)) {
20
+ return Promise.resolve({
21
+ result: 'skipped',
22
+ reason: [
23
+ 'Insufficient fee per gas'
24
+ ]
25
+ });
24
26
  }
25
- return __classPrivateFieldGet(this, _GasTxValidator_instances, "m", _GasTxValidator_validateTxFee).call(this, tx);
27
+ return this.#validateTxFee(tx);
26
28
  }
27
- }
28
- _GasTxValidator_log = new WeakMap(), _GasTxValidator_publicDataSource = new WeakMap(), _GasTxValidator_feeJuiceAddress = new WeakMap(), _GasTxValidator_enforceFees = new WeakMap(), _GasTxValidator_gasFees = new WeakMap(), _GasTxValidator_instances = new WeakSet(), _GasTxValidator_shouldSkip = function _GasTxValidator_shouldSkip(tx) {
29
- const gasSettings = tx.data.constants.txContext.gasSettings;
30
- // Skip the tx if its max fees are not enough for the current block's gas fees.
31
- const maxFeesPerGas = gasSettings.maxFeesPerGas;
32
- const notEnoughMaxFees = maxFeesPerGas.feePerDaGas.lt(__classPrivateFieldGet(this, _GasTxValidator_gasFees, "f").feePerDaGas) ||
33
- maxFeesPerGas.feePerL2Gas.lt(__classPrivateFieldGet(this, _GasTxValidator_gasFees, "f").feePerL2Gas);
34
- if (notEnoughMaxFees) {
35
- __classPrivateFieldGet(this, _GasTxValidator_log, "f").warn(`Skipping transaction ${tx.getTxHash()} due to insufficient fee per gas`);
29
+ /**
30
+ * Check whether the tx's max fees are valid for the current block, and skip if not.
31
+ * We skip instead of invalidating since the tx may become elligible later.
32
+ * Note that circuits check max fees even if fee payer is unset, so we
33
+ * keep this validation even if the tx does not pay fees.
34
+ */ #shouldSkip(tx) {
35
+ const gasSettings = tx.data.constants.txContext.gasSettings;
36
+ // Skip the tx if its max fees are not enough for the current block's gas fees.
37
+ const maxFeesPerGas = gasSettings.maxFeesPerGas;
38
+ const notEnoughMaxFees = maxFeesPerGas.feePerDaGas.lt(this.#gasFees.feePerDaGas) || maxFeesPerGas.feePerL2Gas.lt(this.#gasFees.feePerL2Gas);
39
+ if (notEnoughMaxFees) {
40
+ this.#log.warn(`Skipping transaction ${tx.getTxHash()} due to insufficient fee per gas`);
41
+ }
42
+ return notEnoughMaxFees;
36
43
  }
37
- return notEnoughMaxFees;
38
- }, _GasTxValidator_validateTxFee = async function _GasTxValidator_validateTxFee(tx) {
39
- const feePayer = tx.data.feePayer;
40
- // TODO(@spalladino) Eventually remove the is_zero condition as we should always charge fees to every tx
41
- if (feePayer.isZero()) {
42
- if (__classPrivateFieldGet(this, _GasTxValidator_enforceFees, "f")) {
43
- __classPrivateFieldGet(this, _GasTxValidator_log, "f").warn(`Rejecting transaction ${tx.getTxHash()} due to missing fee payer`);
44
- return { result: 'invalid', reason: ['Missing fee payer'] };
44
+ async #validateTxFee(tx) {
45
+ const feePayer = tx.data.feePayer;
46
+ // TODO(@spalladino) Eventually remove the is_zero condition as we should always charge fees to every tx
47
+ if (feePayer.isZero()) {
48
+ if (this.#enforceFees) {
49
+ this.#log.warn(`Rejecting transaction ${tx.getTxHash()} due to missing fee payer`);
50
+ return {
51
+ result: 'invalid',
52
+ reason: [
53
+ 'Missing fee payer'
54
+ ]
55
+ };
56
+ } else {
57
+ return {
58
+ result: 'valid'
59
+ };
60
+ }
45
61
  }
46
- else {
47
- return { result: 'valid' };
62
+ // Compute the maximum fee that this tx may pay, based on its gasLimits and maxFeePerGas
63
+ const feeLimit = tx.data.constants.txContext.gasSettings.getFeeLimit();
64
+ // Read current balance of the feePayer
65
+ const initialBalance = await this.#publicDataSource.storageRead(this.#feeJuiceAddress, await computeFeePayerBalanceStorageSlot(feePayer));
66
+ // If there is a claim in this tx that increases the fee payer balance in Fee Juice, add it to balance
67
+ const setupFns = getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP);
68
+ const increasePublicBalanceSelector = await FunctionSelector.fromSignature('_increase_public_balance((Field),(Field,Field))');
69
+ const claimFunctionCall = setupFns.find((fn)=>fn.callContext.contractAddress.equals(this.#feeJuiceAddress) && fn.callContext.msgSender.equals(this.#feeJuiceAddress) && fn.args.length > 2 && // Public functions get routed through the dispatch function, whose first argument is the target function selector.
70
+ fn.args[0].equals(increasePublicBalanceSelector.toField()) && fn.args[1].equals(feePayer.toField()) && !fn.callContext.isStaticCall);
71
+ // `amount` in the claim function call arguments occupies 2 fields as it is represented as U128.
72
+ const balance = claimFunctionCall ? initialBalance.add(new Fr(U128.fromFields(claimFunctionCall.args.slice(2, 4)).toInteger())) : initialBalance;
73
+ if (balance.lt(feeLimit)) {
74
+ this.#log.warn(`Rejecting transaction due to not enough fee payer balance`, {
75
+ feePayer,
76
+ balance: balance.toBigInt(),
77
+ feeLimit: feeLimit.toBigInt()
78
+ });
79
+ return {
80
+ result: 'invalid',
81
+ reason: [
82
+ 'Insufficient fee payer balance'
83
+ ]
84
+ };
48
85
  }
86
+ return {
87
+ result: 'valid'
88
+ };
49
89
  }
50
- // Compute the maximum fee that this tx may pay, based on its gasLimits and maxFeePerGas
51
- const feeLimit = tx.data.constants.txContext.gasSettings.getFeeLimit();
52
- // Read current balance of the feePayer
53
- const initialBalance = await __classPrivateFieldGet(this, _GasTxValidator_publicDataSource, "f").storageRead(__classPrivateFieldGet(this, _GasTxValidator_feeJuiceAddress, "f"), await computeFeePayerBalanceStorageSlot(feePayer));
54
- // If there is a claim in this tx that increases the fee payer balance in Fee Juice, add it to balance
55
- const setupFns = getExecutionRequestsByPhase(tx, TxExecutionPhase.SETUP);
56
- const increasePublicBalanceSelector = await FunctionSelector.fromSignature('_increase_public_balance((Field),(Field,Field))');
57
- const claimFunctionCall = setupFns.find(fn => fn.callContext.contractAddress.equals(__classPrivateFieldGet(this, _GasTxValidator_feeJuiceAddress, "f")) &&
58
- fn.callContext.msgSender.equals(__classPrivateFieldGet(this, _GasTxValidator_feeJuiceAddress, "f")) &&
59
- fn.args.length > 2 &&
60
- // Public functions get routed through the dispatch function, whose first argument is the target function selector.
61
- fn.args[0].equals(increasePublicBalanceSelector.toField()) &&
62
- fn.args[1].equals(feePayer.toField()) &&
63
- !fn.callContext.isStaticCall);
64
- // `amount` in the claim function call arguments occupies 2 fields as it is represented as U128.
65
- const balance = claimFunctionCall
66
- ? initialBalance.add(new Fr(U128.fromFields(claimFunctionCall.args.slice(2, 4)).toInteger()))
67
- : initialBalance;
68
- if (balance.lt(feeLimit)) {
69
- __classPrivateFieldGet(this, _GasTxValidator_log, "f").warn(`Rejecting transaction due to not enough fee payer balance`, {
70
- feePayer,
71
- balance: balance.toBigInt(),
72
- feeLimit: feeLimit.toBigInt(),
73
- });
74
- return { result: 'invalid', reason: ['Insufficient fee payer balance'] };
75
- }
76
- return { result: 'valid' };
77
- };
78
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZ2FzX3ZhbGlkYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy90eF92YWxpZGF0b3IvZ2FzX3ZhbGlkYXRvci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBLE9BQU8sRUFBVyxnQkFBZ0IsRUFBNkMsTUFBTSxzQkFBc0IsQ0FBQztBQUM1RyxPQUFPLEVBQXFCLEVBQUUsRUFBRSxnQkFBZ0IsRUFBZ0IsTUFBTSxvQkFBb0IsQ0FBQztBQUMzRixPQUFPLEVBQUUsSUFBSSxFQUFFLE1BQU0sdUJBQXVCLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLHVCQUF1QixDQUFDO0FBQ3JELE9BQU8sRUFBRSxpQ0FBaUMsRUFBRSwyQkFBMkIsRUFBRSxNQUFNLHlCQUF5QixDQUFDO0FBT3pHLE1BQU0sT0FBTyxjQUFjO0lBT3pCLFlBQ0UsZ0JBQW1DLEVBQ25DLGVBQTZCLEVBQzdCLFdBQW9CLEVBQ3BCLE9BQWdCOztRQVZsQiw4QkFBTyxZQUFZLENBQUMsK0JBQStCLENBQUMsRUFBQztRQUNyRCxtREFBcUM7UUFDckMsa0RBQStCO1FBQy9CLDhDQUFzQjtRQUN0QiwwQ0FBa0I7UUFRaEIsdUJBQUEsSUFBSSxvQ0FBcUIsZ0JBQWdCLE1BQUEsQ0FBQztRQUMxQyx1QkFBQSxJQUFJLG1DQUFvQixlQUFlLE1BQUEsQ0FBQztRQUN4Qyx1QkFBQSxJQUFJLCtCQUFnQixXQUFXLE1BQUEsQ0FBQztRQUNoQyx1QkFBQSxJQUFJLDJCQUFZLE9BQU8sTUFBQSxDQUFDO0lBQzFCLENBQUM7SUFFRCxVQUFVLENBQUMsRUFBTTtRQUNmLElBQUksdUJBQUEsSUFBSSw2REFBWSxNQUFoQixJQUFJLEVBQWEsRUFBRSxDQUFDLEVBQUUsQ0FBQztZQUN6QixPQUFPLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxNQUFNLEVBQUUsU0FBUyxFQUFFLE1BQU0sRUFBRSxDQUFDLDBCQUEwQixDQUFDLEVBQUUsQ0FBQyxDQUFDO1FBQ3RG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
90
+ }