@aztec/validator-client 1.0.0-staging.0 → 1.0.0-staging.1

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.
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAErD,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AAI9C,OAAO,EAAE,YAAY,EAAS,MAAM,yBAAyB,CAAC;AAC9D,OAAO,KAAK,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,YAAY,CAAC;AAI9C,OAAO,EAEL,KAAK,aAAa,EAElB,KAAK,eAAe,EACpB,KAAK,OAAO,EACZ,KAAK,cAAc,EACpB,MAAM,uBAAuB,CAAC;AAC/B,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAEzD,OAAO,KAAK,EAAE,qBAAqB,EAAgB,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAC5G,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,yBAAyB,CAAC;AACnE,OAAO,KAAK,EAAE,gBAAgB,EAAE,aAAa,EAAE,oBAAoB,EAAE,MAAM,mBAAmB,CAAC;AAC/F,OAAO,EAAmB,KAAK,mBAAmB,EAAE,KAAK,cAAc,EAAE,KAAK,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAS3G,OAAO,EAAE,KAAK,eAAe,EAAE,KAAK,MAAM,EAAsB,MAAM,yBAAyB,CAAC;AAIhG,OAAO,KAAK,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AAEzD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAQlE,MAAM,WAAW,SAAS;IACxB,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACvB,4BAA4B,IAAI,IAAI,CAAC;IAGrC,mBAAmB,CACjB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,EAAE,EACX,cAAc,EAAE,cAAc,EAC9B,GAAG,EAAE,EAAE,EAAE,EACT,eAAe,EAAE,UAAU,GAAG,SAAS,EACvC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC,CAAC;IACtC,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,SAAS,CAAC,CAAC;IAEnG,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/D,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC,CAAC;CAC7G;oCAKqD,UAAU,cAAc;AAH9E;;GAEG;AACH,qBAAa,eAAgB,SAAQ,oBAA2C,YAAW,SAAS,EAAE,OAAO;IAiBzG,OAAO,CAAC,YAAY;IACpB,OAAO,CAAC,QAAQ;IAChB,OAAO,CAAC,UAAU;IAClB,OAAO,CAAC,SAAS;IACjB,OAAO,CAAC,WAAW;IACnB,OAAO,CAAC,mBAAmB;IAC3B,OAAO,CAAC,MAAM;IAGd,OAAO,CAAC,YAAY;IAEpB,OAAO,CAAC,GAAG;IA3Bb,SAAgB,MAAM,EAAE,MAAM,CAAC;IAC/B,OAAO,CAAC,iBAAiB,CAAoB;IAC7C,OAAO,CAAC,OAAO,CAAmB;IAGlC,OAAO,CAAC,gBAAgB,CAAC,CAAgB;IAEzC,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,SAAS,CAAqB;IACtC,OAAO,CAAC,oBAAoB,CAAiB;IAE7C,OAAO,CAAC,sBAAsB,CAAyB;IACvD,OAAO,CAAC,WAAW,CAAe;IAClC,OAAO,CAAC,wBAAwB,CAA8B;gBAGpD,YAAY,EAAE,qBAAqB,EACnC,QAAQ,EAAE,iBAAiB,EAC3B,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,aAAa,EAC1B,mBAAmB,EAAE,mBAAmB,EACxC,MAAM,EAAE,qBAAqB,GACnC,IAAI,CAAC,eAAe,EAAE,wBAAwB,CAAC,GAC/C,IAAI,CAAC,aAAa,EAAE,0BAA0B,GAAG,0BAA0B,GAAG,6BAA6B,CAAC,EACtG,YAAY,GAAE,YAAiC,EACvD,SAAS,GAAE,eAAsC,EACzC,GAAG,yCAA4B;YAmB3B,0BAA0B;IA2BxC,MAAM,CAAC,GAAG,CACR,MAAM,EAAE,qBAAqB,GAC3B,IAAI,CAAC,aAAa,EAAE,0BAA0B,GAAG,0BAA0B,GAAG,6BAA6B,CAAC,EAC9G,YAAY,EAAE,qBAAqB,EACnC,UAAU,EAAE,UAAU,EACtB,SAAS,EAAE,GAAG,EACd,WAAW,EAAE,aAAa,EAC1B,mBAAmB,EAAE,mBAAmB,EACxC,YAAY,GAAE,YAAiC,EAC/C,SAAS,GAAE,eAAsC;IAwB5C,qBAAqB;IAIrB,iBAAiB,CACtB,MAAM,EAAE,OAAO,CACb,IAAI,CAAC,aAAa,EAAE,0BAA0B,GAAG,0BAA0B,GAAG,6BAA6B,CAAC,CAC7G;IAQU,KAAK;IAkBL,IAAI;IAIV,4BAA4B;IAO7B,gBAAgB,CAAC,QAAQ,EAAE,aAAa,EAAE,cAAc,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,EAAE,GAAG,SAAS,CAAC;IA0GhH,OAAO,CAAC,sBAAsB;IAS9B;;;OAGG;IACG,qBAAqB,CAAC,QAAQ,EAAE,aAAa,EAAE,GAAG,EAAE,EAAE,EAAE,EAAE,cAAc,EAAE,EAAE,EAAE,GAAG,OAAO,CAAC,IAAI,CAAC;IAoDpG,OAAO,CAAC,iBAAiB;IAoBzB;;;;;;;;;;;OAWG;IACI,WAAW,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAOrD,mBAAmB,CACvB,WAAW,EAAE,MAAM,EACnB,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,EAAE,EACX,cAAc,EAAE,cAAc,EAC9B,GAAG,EAAE,EAAE,EAAE,EACT,eAAe,EAAE,UAAU,GAAG,SAAS,EACvC,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,GAAG,SAAS,CAAC;IAmB/B,sBAAsB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9D,mBAAmB,CAAC,QAAQ,EAAE,aAAa,EAAE,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,GAAG,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAiDnG,kBAAkB;CAKjC"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
package/dest/validator.js CHANGED
@@ -2,6 +2,7 @@ import { INITIAL_L2_BLOCK_NUM } from '@aztec/constants';
2
2
  import { Buffer32 } from '@aztec/foundation/buffer';
3
3
  import { Fr } from '@aztec/foundation/fields';
4
4
  import { createLogger } from '@aztec/foundation/log';
5
+ import { retryUntil } from '@aztec/foundation/retry';
5
6
  import { RunningPromise } from '@aztec/foundation/running-promise';
6
7
  import { sleep } from '@aztec/foundation/sleep';
7
8
  import { DateProvider, Timer } from '@aztec/foundation/timer';
@@ -121,6 +122,9 @@ const MAX_PROPOSERS_OF_INVALID_BLOCKS = 1000;
121
122
  const slotNumber = proposal.slotNumber.toNumber();
122
123
  const blockNumber = proposal.blockNumber;
123
124
  const proposer = proposal.getSender();
125
+ // Check that I have any address in current committee before attesting
126
+ const inCommittee = await this.epochCache.filterInCommittee(this.keyStore.getAddresses());
127
+ const partOfCommittee = inCommittee.length > 0;
124
128
  const proposalInfo = {
125
129
  slotNumber,
126
130
  blockNumber,
@@ -135,7 +139,9 @@ const MAX_PROPOSERS_OF_INVALID_BLOCKS = 1000;
135
139
  const invalidProposal = await this.blockProposalValidator.validate(proposal);
136
140
  if (invalidProposal) {
137
141
  this.log.warn(`Proposal is not valid, skipping attestation`);
138
- this.metrics.incFailedAttestations(1, 'invalid_proposal');
142
+ if (partOfCommittee) {
143
+ this.metrics.incFailedAttestations(1, 'invalid_proposal');
144
+ }
139
145
  return undefined;
140
146
  }
141
147
  // Check that the parent proposal is a block we know, otherwise reexecution would fail.
@@ -144,10 +150,23 @@ const MAX_PROPOSERS_OF_INVALID_BLOCKS = 1000;
144
150
  // would not be rebroadcasted. But it also means that nodes that have not fully synced would
145
151
  // not rebroadcast the proposal.
146
152
  if (blockNumber > INITIAL_L2_BLOCK_NUM) {
147
- const parentBlock = await this.blockSource.getBlock(blockNumber - 1);
153
+ const config = this.blockBuilder.getConfig();
154
+ const deadline = this.getReexecutionDeadline(proposal, config);
155
+ const currentTime = this.dateProvider.now();
156
+ const timeoutDurationMs = deadline.getTime() - currentTime;
157
+ const parentBlock = timeoutDurationMs <= 0 ? undefined : await retryUntil(async ()=>{
158
+ const block = await this.blockSource.getBlock(blockNumber - 1);
159
+ if (block) {
160
+ return block;
161
+ }
162
+ await this.blockSource.syncImmediate();
163
+ return await this.blockSource.getBlock(blockNumber - 1);
164
+ }, 'Force Archiver Sync', timeoutDurationMs / 1000, 0.5);
148
165
  if (parentBlock === undefined) {
149
166
  this.log.warn(`Parent block for ${blockNumber} not found, skipping attestation`);
150
- this.metrics.incFailedAttestations(1, 'parent_block_not_found');
167
+ if (partOfCommittee) {
168
+ this.metrics.incFailedAttestations(1, 'parent_block_not_found');
169
+ }
151
170
  return undefined;
152
171
  }
153
172
  if (!proposal.payload.header.lastArchiveRoot.equals(parentBlock.archive.root)) {
@@ -156,25 +175,23 @@ const MAX_PROPOSERS_OF_INVALID_BLOCKS = 1000;
156
175
  parentBlockArchiveRoot: parentBlock.archive.root.toString(),
157
176
  ...proposalInfo
158
177
  });
159
- this.metrics.incFailedAttestations(1, 'parent_block_does_not_match');
178
+ if (partOfCommittee) {
179
+ this.metrics.incFailedAttestations(1, 'parent_block_does_not_match');
180
+ }
160
181
  return undefined;
161
182
  }
162
183
  }
163
184
  // Collect txs from the proposal
164
185
  const { missing, txs } = await this.txCollector.collectForBlockProposal(proposal, proposalSender);
165
- // Check that I have any address in current committee before attesting
166
- const inCommittee = await this.epochCache.filterInCommittee(this.keyStore.getAddresses());
167
- if (inCommittee.length === 0) {
168
- this.log.verbose(`No validator in the committee, skipping attestation`);
169
- return undefined;
170
- }
171
186
  // Check that all of the transactions in the proposal are available in the tx pool before attesting
172
187
  if (missing && missing.length > 0) {
173
188
  this.log.warn(`Missing ${missing.length}/${proposal.payload.txHashes.length} txs to attest to proposal`, {
174
189
  ...proposalInfo,
175
190
  missing
176
191
  });
177
- this.metrics.incFailedAttestations(1, 'TransactionsNotAvailableError');
192
+ if (partOfCommittee) {
193
+ this.metrics.incFailedAttestations(1, 'tx_not_available');
194
+ }
178
195
  return undefined;
179
196
  }
180
197
  // Check that I have the same set of l1ToL2Messages as the proposal
@@ -187,7 +204,13 @@ const MAX_PROPOSERS_OF_INVALID_BLOCKS = 1000;
187
204
  computedInHash: computedInHash.toString(),
188
205
  ...proposalInfo
189
206
  });
190
- this.metrics.incFailedAttestations(1, 'in_hash_mismatch');
207
+ if (partOfCommittee) {
208
+ this.metrics.incFailedAttestations(1, 'in_hash_mismatch');
209
+ }
210
+ return undefined;
211
+ }
212
+ if (!partOfCommittee) {
213
+ this.log.verbose(`No validator in the committee, skipping attestation`);
191
214
  return undefined;
192
215
  }
193
216
  // Try re-executing the transactions in the proposal
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/validator-client",
3
- "version": "1.0.0-staging.0",
3
+ "version": "1.0.0-staging.1",
4
4
  "main": "dest/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -64,15 +64,15 @@
64
64
  ]
65
65
  },
66
66
  "dependencies": {
67
- "@aztec/constants": "1.0.0-staging.0",
68
- "@aztec/epoch-cache": "1.0.0-staging.0",
69
- "@aztec/ethereum": "1.0.0-staging.0",
70
- "@aztec/foundation": "1.0.0-staging.0",
71
- "@aztec/p2p": "1.0.0-staging.0",
72
- "@aztec/prover-client": "1.0.0-staging.0",
73
- "@aztec/slasher": "1.0.0-staging.0",
74
- "@aztec/stdlib": "1.0.0-staging.0",
75
- "@aztec/telemetry-client": "1.0.0-staging.0",
67
+ "@aztec/constants": "1.0.0-staging.1",
68
+ "@aztec/epoch-cache": "1.0.0-staging.1",
69
+ "@aztec/ethereum": "1.0.0-staging.1",
70
+ "@aztec/foundation": "1.0.0-staging.1",
71
+ "@aztec/p2p": "1.0.0-staging.1",
72
+ "@aztec/prover-client": "1.0.0-staging.1",
73
+ "@aztec/slasher": "1.0.0-staging.1",
74
+ "@aztec/stdlib": "1.0.0-staging.1",
75
+ "@aztec/telemetry-client": "1.0.0-staging.1",
76
76
  "koa": "^2.16.1",
77
77
  "koa-router": "^12.0.0",
78
78
  "tslib": "^2.4.0",
package/src/validator.ts CHANGED
@@ -4,6 +4,7 @@ import { Buffer32 } from '@aztec/foundation/buffer';
4
4
  import type { EthAddress } from '@aztec/foundation/eth-address';
5
5
  import { Fr } from '@aztec/foundation/fields';
6
6
  import { createLogger } from '@aztec/foundation/log';
7
+ import { retryUntil } from '@aztec/foundation/retry';
7
8
  import { RunningPromise } from '@aztec/foundation/running-promise';
8
9
  import { sleep } from '@aztec/foundation/sleep';
9
10
  import { DateProvider, Timer } from '@aztec/foundation/timer';
@@ -226,6 +227,10 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
226
227
  const blockNumber = proposal.blockNumber;
227
228
  const proposer = proposal.getSender();
228
229
 
230
+ // Check that I have any address in current committee before attesting
231
+ const inCommittee = await this.epochCache.filterInCommittee(this.keyStore.getAddresses());
232
+ const partOfCommittee = inCommittee.length > 0;
233
+
229
234
  const proposalInfo = {
230
235
  slotNumber,
231
236
  blockNumber,
@@ -241,7 +246,9 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
241
246
  const invalidProposal = await this.blockProposalValidator.validate(proposal);
242
247
  if (invalidProposal) {
243
248
  this.log.warn(`Proposal is not valid, skipping attestation`);
244
- this.metrics.incFailedAttestations(1, 'invalid_proposal');
249
+ if (partOfCommittee) {
250
+ this.metrics.incFailedAttestations(1, 'invalid_proposal');
251
+ }
245
252
  return undefined;
246
253
  }
247
254
 
@@ -251,10 +258,34 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
251
258
  // would not be rebroadcasted. But it also means that nodes that have not fully synced would
252
259
  // not rebroadcast the proposal.
253
260
  if (blockNumber > INITIAL_L2_BLOCK_NUM) {
254
- const parentBlock = await this.blockSource.getBlock(blockNumber - 1);
261
+ const config = this.blockBuilder.getConfig();
262
+ const deadline = this.getReexecutionDeadline(proposal, config);
263
+ const currentTime = this.dateProvider.now();
264
+ const timeoutDurationMs = deadline.getTime() - currentTime;
265
+ const parentBlock =
266
+ timeoutDurationMs <= 0
267
+ ? undefined
268
+ : await retryUntil(
269
+ async () => {
270
+ const block = await this.blockSource.getBlock(blockNumber - 1);
271
+ if (block) {
272
+ return block;
273
+ }
274
+ await this.blockSource.syncImmediate();
275
+ return await this.blockSource.getBlock(blockNumber - 1);
276
+ },
277
+ 'Force Archiver Sync',
278
+ timeoutDurationMs / 1000, // Continue retrying until the deadline
279
+ 0.5, // Retry every 500ms
280
+ );
281
+
255
282
  if (parentBlock === undefined) {
256
283
  this.log.warn(`Parent block for ${blockNumber} not found, skipping attestation`);
257
- this.metrics.incFailedAttestations(1, 'parent_block_not_found');
284
+
285
+ if (partOfCommittee) {
286
+ this.metrics.incFailedAttestations(1, 'parent_block_not_found');
287
+ }
288
+
258
289
  return undefined;
259
290
  }
260
291
  if (!proposal.payload.header.lastArchiveRoot.equals(parentBlock.archive.root)) {
@@ -263,7 +294,9 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
263
294
  parentBlockArchiveRoot: parentBlock.archive.root.toString(),
264
295
  ...proposalInfo,
265
296
  });
266
- this.metrics.incFailedAttestations(1, 'parent_block_does_not_match');
297
+ if (partOfCommittee) {
298
+ this.metrics.incFailedAttestations(1, 'parent_block_does_not_match');
299
+ }
267
300
  return undefined;
268
301
  }
269
302
  }
@@ -271,20 +304,15 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
271
304
  // Collect txs from the proposal
272
305
  const { missing, txs } = await this.txCollector.collectForBlockProposal(proposal, proposalSender);
273
306
 
274
- // Check that I have any address in current committee before attesting
275
- const inCommittee = await this.epochCache.filterInCommittee(this.keyStore.getAddresses());
276
- if (inCommittee.length === 0) {
277
- this.log.verbose(`No validator in the committee, skipping attestation`);
278
- return undefined;
279
- }
280
-
281
307
  // Check that all of the transactions in the proposal are available in the tx pool before attesting
282
308
  if (missing && missing.length > 0) {
283
309
  this.log.warn(`Missing ${missing.length}/${proposal.payload.txHashes.length} txs to attest to proposal`, {
284
310
  ...proposalInfo,
285
311
  missing,
286
312
  });
287
- this.metrics.incFailedAttestations(1, 'TransactionsNotAvailableError');
313
+ if (partOfCommittee) {
314
+ this.metrics.incFailedAttestations(1, 'tx_not_available');
315
+ }
288
316
  return undefined;
289
317
  }
290
318
 
@@ -298,7 +326,14 @@ export class ValidatorClient extends (EventEmitter as new () => WatcherEmitter)
298
326
  computedInHash: computedInHash.toString(),
299
327
  ...proposalInfo,
300
328
  });
301
- this.metrics.incFailedAttestations(1, 'in_hash_mismatch');
329
+ if (partOfCommittee) {
330
+ this.metrics.incFailedAttestations(1, 'in_hash_mismatch');
331
+ }
332
+ return undefined;
333
+ }
334
+
335
+ if (!partOfCommittee) {
336
+ this.log.verbose(`No validator in the committee, skipping attestation`);
302
337
  return undefined;
303
338
  }
304
339