@aztec/validator-client 0.86.0-starknet.1 → 0.87.0

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,6 +1,6 @@
1
1
  import type { Fr } from '@aztec/foundation/fields';
2
- import { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
3
- import type { ProposedBlockHeader, StateReference, TxHash } from '@aztec/stdlib/tx';
2
+ import { BlockAttestation, BlockProposal, type BlockProposalOptions } from '@aztec/stdlib/p2p';
3
+ import type { ProposedBlockHeader, StateReference, Tx } from '@aztec/stdlib/tx';
4
4
  import type { ValidatorKeyStore } from '../key_store/interface.js';
5
5
  export declare class ValidationService {
6
6
  private keyStore;
@@ -15,7 +15,7 @@ export declare class ValidationService {
15
15
  *
16
16
  * @returns A block proposal signing the above information (not the current implementation!!!)
17
17
  */
18
- createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: TxHash[]): Promise<BlockProposal>;
18
+ createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], options: BlockProposalOptions): Promise<BlockProposal>;
19
19
  /**
20
20
  * Attest to the given block proposal constructed by the current sequencer
21
21
  *
@@ -1 +1 @@
1
- {"version":3,"file":"validation_service.d.ts","sourceRoot":"","sources":["../../src/duties/validation_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EAAE,gBAAgB,EAAE,aAAa,EAA8C,MAAM,mBAAmB,CAAC;AAChH,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAEpF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,iBAAiB;IAE/C;;;;;;;;;OASG;IACH,mBAAmB,CACjB,WAAW,EAAE,EAAE,EACf,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,EAAE,EACX,cAAc,EAAE,cAAc,EAC9B,GAAG,EAAE,MAAM,EAAE,GACZ,OAAO,CAAC,aAAa,CAAC;IAUzB;;;;;;;;OAQG;IACG,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAS3E"}
1
+ {"version":3,"file":"validation_service.d.ts","sourceRoot":"","sources":["../../src/duties/validation_service.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,EAAE,EAAE,MAAM,0BAA0B,CAAC;AACnD,OAAO,EACL,gBAAgB,EAChB,aAAa,EACb,KAAK,oBAAoB,EAG1B,MAAM,mBAAmB,CAAC;AAC3B,OAAO,KAAK,EAAE,mBAAmB,EAAE,cAAc,EAAE,EAAE,EAAE,MAAM,kBAAkB,CAAC;AAEhF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,qBAAa,iBAAiB;IAChB,OAAO,CAAC,QAAQ;gBAAR,QAAQ,EAAE,iBAAiB;IAE/C;;;;;;;;;OASG;IACG,mBAAmB,CACvB,WAAW,EAAE,EAAE,EACf,MAAM,EAAE,mBAAmB,EAC3B,OAAO,EAAE,EAAE,EACX,cAAc,EAAE,cAAc,EAC9B,GAAG,EAAE,EAAE,EAAE,EACT,OAAO,EAAE,oBAAoB,GAC5B,OAAO,CAAC,aAAa,CAAC;IAazB;;;;;;;;OAQG;IACG,gBAAgB,CAAC,QAAQ,EAAE,aAAa,GAAG,OAAO,CAAC,gBAAgB,CAAC;CAS3E"}
@@ -15,9 +15,11 @@ export class ValidationService {
15
15
  * @param txs - TxHash[] ordered list of transactions
16
16
  *
17
17
  * @returns A block proposal signing the above information (not the current implementation!!!)
18
- */ createBlockProposal(blockNumber, header, archive, stateReference, txs) {
18
+ */ async createBlockProposal(blockNumber, header, archive, stateReference, txs, options) {
19
19
  const payloadSigner = (payload)=>this.keyStore.signMessage(payload);
20
- return BlockProposal.createProposalFromSigner(blockNumber, new ConsensusPayload(header, archive, stateReference, txs), payloadSigner);
20
+ // TODO: check if this is calculated earlier / can not be recomputed
21
+ const txHashes = await Promise.all(txs.map((tx)=>tx.getTxHash()));
22
+ return BlockProposal.createProposalFromSigner(blockNumber, new ConsensusPayload(header, archive, stateReference, txHashes), options.publishFullTxs ? txs : undefined, payloadSigner);
21
23
  }
22
24
  /**
23
25
  * Attest to the given block proposal constructed by the current sequencer
@@ -4,8 +4,8 @@ import { Fr } from '@aztec/foundation/fields';
4
4
  import { DateProvider, type Timer } from '@aztec/foundation/timer';
5
5
  import type { P2P } from '@aztec/p2p';
6
6
  import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
7
- import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
8
- import type { ProposedBlockHeader, StateReference, Tx, TxHash } from '@aztec/stdlib/tx';
7
+ import type { BlockAttestation, BlockProposal, BlockProposalOptions } from '@aztec/stdlib/p2p';
8
+ import type { ProposedBlockHeader, StateReference, Tx } from '@aztec/stdlib/tx';
9
9
  import { type TelemetryClient, WithTracer } from '@aztec/telemetry-client';
10
10
  import type { ValidatorClientConfig } from './config.js';
11
11
  import type { ValidatorKeyStore } from './key_store/interface.js';
@@ -27,9 +27,9 @@ export interface Validator {
27
27
  start(): Promise<void>;
28
28
  registerBlockProposalHandler(): void;
29
29
  registerBlockBuilder(blockBuilder: BlockBuilderCallback): void;
30
- createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: TxHash[]): Promise<BlockProposal | undefined>;
31
- attestToProposal(proposal: BlockProposal): void;
32
- broadcastBlockProposal(proposal: BlockProposal): void;
30
+ createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], options: BlockProposalOptions): Promise<BlockProposal | undefined>;
31
+ attestToProposal(proposal: BlockProposal): Promise<BlockAttestation | undefined>;
32
+ broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
33
33
  collectAttestations(proposal: BlockProposal, required: number, deadline: Date): Promise<BlockAttestation[]>;
34
34
  }
35
35
  /**
@@ -69,7 +69,7 @@ export declare class ValidatorClient extends WithTracer implements Validator {
69
69
  * Re-execute the transactions in the proposal and check that the state updates match the header state
70
70
  * @param proposal - The proposal to re-execute
71
71
  */
72
- reExecuteTransactions(proposal: BlockProposal): Promise<void>;
72
+ reExecuteTransactions(proposal: BlockProposal, txs: Tx[]): Promise<void>;
73
73
  /**
74
74
  * Ensure that all of the transactions in the proposal are available in the tx pool before attesting
75
75
  *
@@ -78,9 +78,9 @@ export declare class ValidatorClient extends WithTracer implements Validator {
78
78
  * 3. If we cannot retrieve them from the network, throw an error
79
79
  * @param proposal - The proposal to attest to
80
80
  */
81
- ensureTransactionsAreAvailable(proposal: BlockProposal): Promise<void>;
82
- createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: TxHash[]): Promise<BlockProposal | undefined>;
83
- broadcastBlockProposal(proposal: BlockProposal): void;
81
+ ensureTransactionsAreAvailable(proposal: BlockProposal): Promise<Tx[]>;
82
+ createBlockProposal(blockNumber: Fr, header: ProposedBlockHeader, archive: Fr, stateReference: StateReference, txs: Tx[], options: BlockProposalOptions): Promise<BlockProposal | undefined>;
83
+ broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
84
84
  collectAttestations(proposal: BlockProposal, required: number, deadline: Date): Promise<BlockAttestation[]>;
85
85
  private doAttestToProposal;
86
86
  }
@@ -1 +1 @@
1
- {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"validator.d.ts","sourceRoot":"","sources":["../src/validator.ts"],"names":[],"mappings":"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"}
package/dest/validator.js CHANGED
@@ -147,10 +147,10 @@ import { ValidatorMetrics } from './metrics.js';
147
147
  // Check that all of the transactions in the proposal are available in the tx pool before attesting
148
148
  this.log.verbose(`Processing attestation for slot ${slotNumber}`, proposalInfo);
149
149
  try {
150
- await this.ensureTransactionsAreAvailable(proposal);
150
+ const txs = await this.ensureTransactionsAreAvailable(proposal);
151
151
  if (this.config.validatorReexecute) {
152
152
  this.log.verbose(`Re-executing transactions in the proposal before attesting`);
153
- await this.reExecuteTransactions(proposal);
153
+ await this.reExecuteTransactions(proposal, txs);
154
154
  }
155
155
  } catch (error) {
156
156
  this.metrics.incFailedAttestations(error instanceof Error ? error.name : 'unknown');
@@ -173,10 +173,9 @@ import { ValidatorMetrics } from './metrics.js';
173
173
  /**
174
174
  * Re-execute the transactions in the proposal and check that the state updates match the header state
175
175
  * @param proposal - The proposal to re-execute
176
- */ async reExecuteTransactions(proposal) {
176
+ */ async reExecuteTransactions(proposal, txs) {
177
177
  const { header, txHashes } = proposal.payload;
178
- const txs = (await Promise.all(txHashes.map((tx)=>this.p2pClient.getTxByHash(tx)))).filter((tx)=>tx !== undefined);
179
- // If we cannot request all of the transactions, then we should fail
178
+ // If we do not have all of the transactions, then we should fail
180
179
  if (txs.length !== txHashes.length) {
181
180
  const foundTxHashes = await Promise.all(txs.map(async (tx)=>await tx.getTxHash()));
182
181
  const missingTxHashes = txHashes.filter((txHash)=>!foundTxHashes.includes(txHash));
@@ -215,29 +214,82 @@ import { ValidatorMetrics } from './metrics.js';
215
214
  * 3. If we cannot retrieve them from the network, throw an error
216
215
  * @param proposal - The proposal to attest to
217
216
  */ async ensureTransactionsAreAvailable(proposal) {
217
+ if (proposal.payload.txHashes.length === 0) {
218
+ this.log.verbose(`Received block proposal with no transactions, skipping transaction availability check`);
219
+ return [];
220
+ }
221
+ // Is this a new style proposal?
222
+ if (proposal.txs && proposal.txs.length > 0 && proposal.txs.length === proposal.payload.txHashes.length) {
223
+ // Yes, any txs that we already have we should use
224
+ this.log.info(`Using new style proposal with ${proposal.txs.length} transactions`);
225
+ // Request from the pool based on the signed hashes in the payload
226
+ const hashesFromPayload = proposal.payload.txHashes;
227
+ const txsToUse = await this.p2pClient.getTxsByHashFromPool(hashesFromPayload);
228
+ const missingTxs = txsToUse.filter((tx)=>tx === undefined).length;
229
+ if (missingTxs > 0) {
230
+ this.log.verbose(`Missing ${missingTxs}/${hashesFromPayload.length} transactions in the tx pool, will attempt to take from the proposal`);
231
+ }
232
+ let usedFromProposal = 0;
233
+ // Fill any holes with txs in the proposal, provided their hash matches the hash in the payload
234
+ for(let i = 0; i < txsToUse.length; i++){
235
+ if (txsToUse[i] === undefined) {
236
+ // We don't have the transaction, take from the proposal, provided the hash is the same
237
+ const hashOfTxInProposal = await proposal.txs[i].getTxHash();
238
+ if (hashOfTxInProposal.equals(hashesFromPayload[i])) {
239
+ // Hash is equal, we can use the tx from the proposal
240
+ txsToUse[i] = proposal.txs[i];
241
+ usedFromProposal++;
242
+ } else {
243
+ this.log.warn(`Unable to take tx: ${hashOfTxInProposal.toString()} from the proposal, it does not match payload hash: ${hashesFromPayload[i].toString()}`);
244
+ }
245
+ }
246
+ }
247
+ // See if we still have any holes, if there are then we were not successful and will try the old method
248
+ if (txsToUse.some((tx)=>tx === undefined)) {
249
+ this.log.warn(`Failed to use transactions from proposal. Falling back to old proposal logic`);
250
+ } else {
251
+ this.log.info(`Successfully used ${usedFromProposal}/${hashesFromPayload.length} transactions from the proposal`);
252
+ await this.p2pClient.validate(txsToUse);
253
+ return txsToUse;
254
+ }
255
+ }
256
+ this.log.info(`Using old style proposal with ${proposal.payload.txHashes.length} transactions`);
257
+ // Old style proposal, we will perform a request by hash from pool
258
+ // This will request from network any txs that are missing
218
259
  const txHashes = proposal.payload.txHashes;
260
+ // This part is just for logging that we are requesting from the network
219
261
  const availability = await this.p2pClient.hasTxsInPool(txHashes);
220
- const missingTxs = txHashes.filter((_, index)=>!availability[index]);
221
- if (missingTxs.length === 0) {
222
- return; // All transactions are available
262
+ const notAvailable = availability.filter((availability)=>availability === false);
263
+ if (notAvailable.length) {
264
+ this.log.verbose(`Missing ${notAvailable.length} transactions in the tx pool, will need to request from the network`);
223
265
  }
224
- this.log.verbose(`Missing ${missingTxs.length} transactions in the tx pool, requesting from the network`);
225
- const requestedTxs = await this.p2pClient.requestTxsByHash(missingTxs);
226
- if (requestedTxs.some((tx)=>tx === undefined)) {
266
+ // This will request from the network any txs that are missing
267
+ const retrievedTxs = await this.p2pClient.getTxsByHash(txHashes);
268
+ const missingTxs = retrievedTxs.map((tx, index)=>{
269
+ // Return the hash of any that we did not get
270
+ if (tx === undefined) {
271
+ return txHashes[index];
272
+ } else {
273
+ return undefined;
274
+ }
275
+ }).filter((hash)=>hash !== undefined);
276
+ if (missingTxs.length > 0) {
227
277
  throw new TransactionsNotAvailableError(missingTxs);
228
278
  }
279
+ await this.p2pClient.validate(retrievedTxs);
280
+ return retrievedTxs;
229
281
  }
230
- async createBlockProposal(blockNumber, header, archive, stateReference, txs) {
282
+ async createBlockProposal(blockNumber, header, archive, stateReference, txs, options) {
231
283
  if (this.previousProposal?.slotNumber.equals(header.slotNumber)) {
232
284
  this.log.verbose(`Already made a proposal for the same slot, skipping proposal`);
233
285
  return Promise.resolve(undefined);
234
286
  }
235
- const newProposal = await this.validationService.createBlockProposal(blockNumber, header, archive, stateReference, txs);
287
+ const newProposal = await this.validationService.createBlockProposal(blockNumber, header, archive, stateReference, txs, options);
236
288
  this.previousProposal = newProposal;
237
289
  return newProposal;
238
290
  }
239
- broadcastBlockProposal(proposal) {
240
- this.p2pClient.broadcastProposal(proposal);
291
+ async broadcastBlockProposal(proposal) {
292
+ await this.p2pClient.broadcastProposal(proposal);
241
293
  }
242
294
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962)
243
295
  async collectAttestations(proposal, required, deadline) {
@@ -283,7 +335,7 @@ import { ValidatorMetrics } from './metrics.js';
283
335
  function validatePrivateKey(privateKey) {
284
336
  try {
285
337
  return Buffer32.fromString(privateKey);
286
- } catch (error) {
338
+ } catch {
287
339
  throw new InvalidValidatorPrivateKeyError();
288
340
  }
289
341
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@aztec/validator-client",
3
- "version": "0.86.0-starknet.1",
3
+ "version": "0.87.0",
4
4
  "main": "dest/index.js",
5
5
  "type": "module",
6
6
  "exports": {
@@ -60,13 +60,13 @@
60
60
  ]
61
61
  },
62
62
  "dependencies": {
63
- "@aztec/constants": "0.86.0-starknet.1",
64
- "@aztec/epoch-cache": "0.86.0-starknet.1",
65
- "@aztec/ethereum": "0.86.0-starknet.1",
66
- "@aztec/foundation": "0.86.0-starknet.1",
67
- "@aztec/p2p": "0.86.0-starknet.1",
68
- "@aztec/stdlib": "0.86.0-starknet.1",
69
- "@aztec/telemetry-client": "0.86.0-starknet.1",
63
+ "@aztec/constants": "0.87.0",
64
+ "@aztec/epoch-cache": "0.87.0",
65
+ "@aztec/ethereum": "0.87.0",
66
+ "@aztec/foundation": "0.87.0",
67
+ "@aztec/p2p": "0.87.0",
68
+ "@aztec/stdlib": "0.87.0",
69
+ "@aztec/telemetry-client": "0.87.0",
70
70
  "koa": "^2.16.1",
71
71
  "koa-router": "^12.0.0",
72
72
  "tslib": "^2.4.0",
@@ -75,11 +75,11 @@
75
75
  "devDependencies": {
76
76
  "@jest/globals": "^29.5.0",
77
77
  "@types/jest": "^29.5.0",
78
- "@types/node": "^18.7.23",
78
+ "@types/node": "^22.15.17",
79
79
  "jest": "^29.5.0",
80
80
  "jest-mock-extended": "^3.0.7",
81
81
  "ts-node": "^10.9.1",
82
- "typescript": "^5.0.4"
82
+ "typescript": "^5.3.3"
83
83
  },
84
84
  "files": [
85
85
  "dest",
@@ -88,6 +88,6 @@
88
88
  ],
89
89
  "types": "./dest/index.d.ts",
90
90
  "engines": {
91
- "node": ">=18"
91
+ "node": ">=20.10"
92
92
  }
93
93
  }
@@ -1,8 +1,14 @@
1
1
  import { Buffer32 } from '@aztec/foundation/buffer';
2
2
  import { keccak256 } from '@aztec/foundation/crypto';
3
3
  import type { Fr } from '@aztec/foundation/fields';
4
- import { BlockAttestation, BlockProposal, ConsensusPayload, SignatureDomainSeparator } from '@aztec/stdlib/p2p';
5
- import type { ProposedBlockHeader, StateReference, TxHash } from '@aztec/stdlib/tx';
4
+ import {
5
+ BlockAttestation,
6
+ BlockProposal,
7
+ type BlockProposalOptions,
8
+ ConsensusPayload,
9
+ SignatureDomainSeparator,
10
+ } from '@aztec/stdlib/p2p';
11
+ import type { ProposedBlockHeader, StateReference, Tx } from '@aztec/stdlib/tx';
6
12
 
7
13
  import type { ValidatorKeyStore } from '../key_store/interface.js';
8
14
 
@@ -19,18 +25,22 @@ export class ValidationService {
19
25
  *
20
26
  * @returns A block proposal signing the above information (not the current implementation!!!)
21
27
  */
22
- createBlockProposal(
28
+ async createBlockProposal(
23
29
  blockNumber: Fr,
24
30
  header: ProposedBlockHeader,
25
31
  archive: Fr,
26
32
  stateReference: StateReference,
27
- txs: TxHash[],
33
+ txs: Tx[],
34
+ options: BlockProposalOptions,
28
35
  ): Promise<BlockProposal> {
29
36
  const payloadSigner = (payload: Buffer32) => this.keyStore.signMessage(payload);
37
+ // TODO: check if this is calculated earlier / can not be recomputed
38
+ const txHashes = await Promise.all(txs.map(tx => tx.getTxHash()));
30
39
 
31
40
  return BlockProposal.createProposalFromSigner(
32
41
  blockNumber,
33
- new ConsensusPayload(header, archive, stateReference, txs),
42
+ new ConsensusPayload(header, archive, stateReference, txHashes),
43
+ options.publishFullTxs ? txs : undefined,
34
44
  payloadSigner,
35
45
  );
36
46
  }
package/src/validator.ts CHANGED
@@ -10,7 +10,7 @@ import { DateProvider, type Timer } from '@aztec/foundation/timer';
10
10
  import type { P2P } from '@aztec/p2p';
11
11
  import { BlockProposalValidator } from '@aztec/p2p/msg_validators';
12
12
  import type { L2Block, L2BlockSource } from '@aztec/stdlib/block';
13
- import type { BlockAttestation, BlockProposal } from '@aztec/stdlib/p2p';
13
+ import type { BlockAttestation, BlockProposal, BlockProposalOptions } from '@aztec/stdlib/p2p';
14
14
  import type { ProposedBlockHeader, StateReference, Tx, TxHash } from '@aztec/stdlib/tx';
15
15
  import { type TelemetryClient, WithTracer, getTelemetryClient } from '@aztec/telemetry-client';
16
16
 
@@ -58,11 +58,12 @@ export interface Validator {
58
58
  header: ProposedBlockHeader,
59
59
  archive: Fr,
60
60
  stateReference: StateReference,
61
- txs: TxHash[],
61
+ txs: Tx[],
62
+ options: BlockProposalOptions,
62
63
  ): Promise<BlockProposal | undefined>;
63
- attestToProposal(proposal: BlockProposal): void;
64
+ attestToProposal(proposal: BlockProposal): Promise<BlockAttestation | undefined>;
64
65
 
65
- broadcastBlockProposal(proposal: BlockProposal): void;
66
+ broadcastBlockProposal(proposal: BlockProposal): Promise<void>;
66
67
  collectAttestations(proposal: BlockProposal, required: number, deadline: Date): Promise<BlockAttestation[]>;
67
68
  }
68
69
 
@@ -246,11 +247,11 @@ export class ValidatorClient extends WithTracer implements Validator {
246
247
  // Check that all of the transactions in the proposal are available in the tx pool before attesting
247
248
  this.log.verbose(`Processing attestation for slot ${slotNumber}`, proposalInfo);
248
249
  try {
249
- await this.ensureTransactionsAreAvailable(proposal);
250
+ const txs = await this.ensureTransactionsAreAvailable(proposal);
250
251
 
251
252
  if (this.config.validatorReexecute) {
252
253
  this.log.verbose(`Re-executing transactions in the proposal before attesting`);
253
- await this.reExecuteTransactions(proposal);
254
+ await this.reExecuteTransactions(proposal, txs);
254
255
  }
255
256
  } catch (error: any) {
256
257
  this.metrics.incFailedAttestations(error instanceof Error ? error.name : 'unknown');
@@ -278,14 +279,10 @@ export class ValidatorClient extends WithTracer implements Validator {
278
279
  * Re-execute the transactions in the proposal and check that the state updates match the header state
279
280
  * @param proposal - The proposal to re-execute
280
281
  */
281
- async reExecuteTransactions(proposal: BlockProposal) {
282
+ async reExecuteTransactions(proposal: BlockProposal, txs: Tx[]) {
282
283
  const { header, txHashes } = proposal.payload;
283
284
 
284
- const txs = (await Promise.all(txHashes.map(tx => this.p2pClient.getTxByHash(tx)))).filter(
285
- tx => tx !== undefined,
286
- ) as Tx[];
287
-
288
- // If we cannot request all of the transactions, then we should fail
285
+ // If we do not have all of the transactions, then we should fail
289
286
  if (txs.length !== txHashes.length) {
290
287
  const foundTxHashes = await Promise.all(txs.map(async tx => await tx.getTxHash()));
291
288
  const missingTxHashes = txHashes.filter(txHash => !foundTxHashes.includes(txHash));
@@ -331,21 +328,95 @@ export class ValidatorClient extends WithTracer implements Validator {
331
328
  * 3. If we cannot retrieve them from the network, throw an error
332
329
  * @param proposal - The proposal to attest to
333
330
  */
334
- async ensureTransactionsAreAvailable(proposal: BlockProposal) {
331
+ async ensureTransactionsAreAvailable(proposal: BlockProposal): Promise<Tx[]> {
332
+ if (proposal.payload.txHashes.length === 0) {
333
+ this.log.verbose(`Received block proposal with no transactions, skipping transaction availability check`);
334
+ return [];
335
+ }
336
+ // Is this a new style proposal?
337
+ if (proposal.txs && proposal.txs.length > 0 && proposal.txs.length === proposal.payload.txHashes.length) {
338
+ // Yes, any txs that we already have we should use
339
+ this.log.info(`Using new style proposal with ${proposal.txs.length} transactions`);
340
+
341
+ // Request from the pool based on the signed hashes in the payload
342
+ const hashesFromPayload = proposal.payload.txHashes;
343
+ const txsToUse = await this.p2pClient.getTxsByHashFromPool(hashesFromPayload);
344
+
345
+ const missingTxs = txsToUse.filter(tx => tx === undefined).length;
346
+ if (missingTxs > 0) {
347
+ this.log.verbose(
348
+ `Missing ${missingTxs}/${hashesFromPayload.length} transactions in the tx pool, will attempt to take from the proposal`,
349
+ );
350
+ }
351
+
352
+ let usedFromProposal = 0;
353
+
354
+ // Fill any holes with txs in the proposal, provided their hash matches the hash in the payload
355
+ for (let i = 0; i < txsToUse.length; i++) {
356
+ if (txsToUse[i] === undefined) {
357
+ // We don't have the transaction, take from the proposal, provided the hash is the same
358
+ const hashOfTxInProposal = await proposal.txs[i].getTxHash();
359
+ if (hashOfTxInProposal.equals(hashesFromPayload[i])) {
360
+ // Hash is equal, we can use the tx from the proposal
361
+ txsToUse[i] = proposal.txs[i];
362
+ usedFromProposal++;
363
+ } else {
364
+ this.log.warn(
365
+ `Unable to take tx: ${hashOfTxInProposal.toString()} from the proposal, it does not match payload hash: ${hashesFromPayload[
366
+ i
367
+ ].toString()}`,
368
+ );
369
+ }
370
+ }
371
+ }
372
+
373
+ // See if we still have any holes, if there are then we were not successful and will try the old method
374
+ if (txsToUse.some(tx => tx === undefined)) {
375
+ this.log.warn(`Failed to use transactions from proposal. Falling back to old proposal logic`);
376
+ } else {
377
+ this.log.info(
378
+ `Successfully used ${usedFromProposal}/${hashesFromPayload.length} transactions from the proposal`,
379
+ );
380
+
381
+ await this.p2pClient.validate(txsToUse as Tx[]);
382
+ return txsToUse as Tx[];
383
+ }
384
+ }
385
+
386
+ this.log.info(`Using old style proposal with ${proposal.payload.txHashes.length} transactions`);
387
+
388
+ // Old style proposal, we will perform a request by hash from pool
389
+ // This will request from network any txs that are missing
335
390
  const txHashes: TxHash[] = proposal.payload.txHashes;
391
+
392
+ // This part is just for logging that we are requesting from the network
336
393
  const availability = await this.p2pClient.hasTxsInPool(txHashes);
337
- const missingTxs = txHashes.filter((_, index) => !availability[index]);
394
+ const notAvailable = availability.filter(availability => availability === false);
395
+ if (notAvailable.length) {
396
+ this.log.verbose(
397
+ `Missing ${notAvailable.length} transactions in the tx pool, will need to request from the network`,
398
+ );
399
+ }
338
400
 
339
- if (missingTxs.length === 0) {
340
- return; // All transactions are available
401
+ // This will request from the network any txs that are missing
402
+ const retrievedTxs = await this.p2pClient.getTxsByHash(txHashes);
403
+ const missingTxs = retrievedTxs
404
+ .map((tx, index) => {
405
+ // Return the hash of any that we did not get
406
+ if (tx === undefined) {
407
+ return txHashes[index];
408
+ } else {
409
+ return undefined;
410
+ }
411
+ })
412
+ .filter(hash => hash !== undefined);
413
+ if (missingTxs.length > 0) {
414
+ throw new TransactionsNotAvailableError(missingTxs as TxHash[]);
341
415
  }
342
416
 
343
- this.log.verbose(`Missing ${missingTxs.length} transactions in the tx pool, requesting from the network`);
417
+ await this.p2pClient.validate(retrievedTxs as Tx[]);
344
418
 
345
- const requestedTxs = await this.p2pClient.requestTxsByHash(missingTxs);
346
- if (requestedTxs.some(tx => tx === undefined)) {
347
- throw new TransactionsNotAvailableError(missingTxs);
348
- }
419
+ return retrievedTxs as Tx[];
349
420
  }
350
421
 
351
422
  async createBlockProposal(
@@ -353,7 +424,8 @@ export class ValidatorClient extends WithTracer implements Validator {
353
424
  header: ProposedBlockHeader,
354
425
  archive: Fr,
355
426
  stateReference: StateReference,
356
- txs: TxHash[],
427
+ txs: Tx[],
428
+ options: BlockProposalOptions,
357
429
  ): Promise<BlockProposal | undefined> {
358
430
  if (this.previousProposal?.slotNumber.equals(header.slotNumber)) {
359
431
  this.log.verbose(`Already made a proposal for the same slot, skipping proposal`);
@@ -366,13 +438,14 @@ export class ValidatorClient extends WithTracer implements Validator {
366
438
  archive,
367
439
  stateReference,
368
440
  txs,
441
+ options,
369
442
  );
370
443
  this.previousProposal = newProposal;
371
444
  return newProposal;
372
445
  }
373
446
 
374
- broadcastBlockProposal(proposal: BlockProposal): void {
375
- this.p2pClient.broadcastProposal(proposal);
447
+ async broadcastBlockProposal(proposal: BlockProposal): Promise<void> {
448
+ await this.p2pClient.broadcastProposal(proposal);
376
449
  }
377
450
 
378
451
  // TODO(https://github.com/AztecProtocol/aztec-packages/issues/7962)
@@ -429,7 +502,7 @@ export class ValidatorClient extends WithTracer implements Validator {
429
502
  function validatePrivateKey(privateKey: string): Buffer32 {
430
503
  try {
431
504
  return Buffer32.fromString(privateKey);
432
- } catch (error) {
505
+ } catch {
433
506
  throw new InvalidValidatorPrivateKeyError();
434
507
  }
435
508
  }